您的位置:首页 > 其它

BZOJ 4736/UOJ #274. 【清华集训2016】温暖会指引我们前行 LCT边权操作

2017-12-20 20:28 489 查看








维护动态最大生成树

最开始YY了一个 线段树分治 kruskal重构树

然后觉得复杂度不对? 不过BJ对kruskal重构树也仅仅算理解 没写过。。

希望有人带带 QWQ 告诉我对不对、怎么做哦~

LCT维护最大生成树

加入一条边时

若两点未联通 直接加

否则找到两点路径上最小的边 看能不能替换掉

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=400100,inf=0X3f3f3f3f;

int n;

int fa
,ch
[2];
int mn
,sum
,tim
,len
;
bool rev
;

inline bool isroot(int x)
{return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}

inline void pushup(int x)
{
mn[x]=x;
int ls=ch[x][0],rs=ch[x][1];
if(ls && tim[mn[ls]]<tim[mn[x]]) mn[x]=mn[ls];
if(rs && tim[mn[rs]]<tim[mn[x]]) mn[x]=mn[rs];
sum[x]=sum[rs]+sum[ls]+len[x];
}

inline void pushdown(int x)
{
if(rev[x])
{
rev[x]=0;
if(ch[x][0]) rev[ch[x][0]]^=1;
if(ch[x][1]) rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
}

void getdown(int x)
{if(!isroot(x))getdown(fa[x]);pushdown(x);}

inline void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
l=(ch[y][1]==x);r=l^1;
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
pushup(y);pushup(x);
}

void splay(int x)
{
getdown(x);
int y,z;
while(!isroot(x))
{
y=fa[x];z=fa[y];
if(!isroot(y))
{
if((ch[z][0]==y)^(ch[y][0]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
}

void access(int x)
{int t=0;while(x){splay(x);ch[x][1]=t;pushup(x);t=x;x=fa[x];}}

void rever(int x)
{access(x);splay(x);rev[x]^=1;}

int find(int x)
{access(x);splay(x);while(ch[x][0])x=ch[x][0];splay(x);return x;}

void split(int u,int v)
{rever(u);access(v);splay(v);}

void link(int u,int v)
{rever(u);fa[u]=v;}

void cut(int u,int v)
{split(u,v);fa[u]=0;ch[v][0]=0;pushup(u);pushup(v);}

int query_sum(int u,int v)
{split(u,v);return sum[v];}

int U
,V
;

int main()
{
n=read();int Q=read();
register int i,j,u,v,pos,tmp;
for(i=1;i<=n;++i) tim[i]=inf,mn[i]=i;
char opt[10];
while(Q--)
{
scanf("%s",opt);
switch(opt[0])
{
case 'f':
pos=read()+n+1;
u=U[pos]=read()+1;v=V[pos]=read()+1;
mn[pos]=pos;
tim[pos]=read();sum[pos]=len[pos]=read();
if(find(u)!=find(v))
link(u,pos),link(v,pos);
else
{
split(u,v);
tmp=mn[v];i=U[tmp];j=V[tmp];
if(tim[tmp]<tim[pos])
cut(tmp,i),cut(tmp,j),
link(pos,u),link(pos,v);
}
break;
case 'm':
u=read()+1;v=read()+1;
if(find(u)==find(v))
print(query_sum(u,v)),puts("");
else puts("-1");
break;
case 'c':
pos=read()+n+1;
splay(pos);
len[pos]=read();
pushup(pos);
break;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: