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

来源:互联网 发布:python 签到脚本 编辑:程序博客网 时间:2024/05/17 10:41



维护动态最大生成树

最开始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[N],ch[N][2];int mn[N],sum[N],tim[N],len[N];bool rev[N];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];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[N],V[N];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;}