BZOJ 4736/UOJ #274. 【清華集訓2016】溫暖會指引我們前行 LCT邊權操作
阿新 • • 發佈:2019-02-04
維護動態最大生成樹
最開始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];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[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; }