BZOJ2816 [ZJOI2012]網路
阿新 • • 發佈:2019-01-08
BZOJ2816 [ZJOI2012]網路
題面描述
題目分析
首先可以發現這題,如果邊都是一個顏色,那麼\(1\)操作就啥用都沒有了,就變成了一個裸的樹鏈剖分。。。或者我們也可以用lct來實現這個過程。那麼我們又發現這個顏色種類確實不多啊,我們完全可以在\(O(mlognC)\)的時間複雜度內通過。於是我們可以考慮對於每一種顏色都建立一棵lct,然後更改邊的顏色的時候,就斷掉原來顏色lct上的邊,在更改的顏色的lct上連邊。
那麼對於\(0\)操作,暴力修改所有lct就可以了。
對於\(1\)那幾個鬼畜的輸出,可以考慮用一個map來記錄是否有邊相連。然後對於連通性的判斷可以用findroot操作實現。
是程式碼呢
#include <bits/stdc++.h> using namespace std; #define m_p(x,y) make_pair(x,y) const int MAXN=1e4+7; int color[MAXN][15],n,m,c,q,v[MAXN]; map< pair<int,int>,int > mp; #define lc ch[x][0] #define rc ch[x][1] inline int read() { int x=0,c=1; char ch=' '; while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); while(ch=='-')c*=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*c; } struct lct{ int ch[MAXN][2],f[MAXN],mx[MAXN],r[MAXN],st[MAXN]; inline bool nroot(int x){return ch[f[x]][0]==x||ch[f[x]][1]==x;} inline void pushr(int x){swap(lc,rc);r[x]^=1;} inline void pushup(int x){mx[x]=max(v[x],max(mx[lc],mx[rc]));} inline void pushdown(int x){ if(r[x]){ if(lc) pushr(lc); if(rc) pushr(rc); r[x]=0; } } inline void rotate(int x){ int y=f[x],z=f[y],kind=ch[y][1]==x,w=ch[x][!kind]; if(nroot(y)) ch[z][ch[z][1]==y]=x;ch[x][!kind]=y;ch[y][kind]=w; if(w) f[w]=y;f[f[y]=x]=z; pushup(y); } inline void splay(int x){ int y=x,z=0; st[++z]=y; while(nroot(y)) st[++z]=y=f[y]; while(z) pushdown(st[z--]); while(nroot(x)){ y=f[x],z=f[y]; if(nroot(y)) rotate((ch[y][0]==x)^(ch[z][0]==y)?x:y); rotate(x); } pushup(x); } inline void access(int x){ for(int y=0;x;x=f[y=x]) splay(x),rc=y,pushup(x); } inline void makeroot(int x){ access(x);splay(x);pushr(x); } inline void split(int x,int y){ makeroot(x);access(y);splay(y); } inline int findroot(int x){ access(x);splay(x); while(lc) pushdown(x),x=lc; splay(x); return x; } inline void link(int x,int y){ makeroot(x); if(findroot(y)!=x) f[x]=y; } inline void cut(int x,int y){ makeroot(x); if(findroot(y)==x&&f[y]==x&&!ch[y][0]){ f[y]=ch[x][1]=0; pushup(x); } } }LCT[13]; int main() { n=read();m=read();c=read();q=read(); for(int i=1;i<=n;i++) v[i]=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),col=read()+1; if(x>y) swap(x,y); mp[m_p(x,y)]=col; color[x][col]++; color[y][col]++; LCT[col].link(x,y); } while(q--){ int fl=read(); if(fl==0){ int x=read(),y=read(); for(int i=1;i<=c;i++) LCT[i].splay(x); v[x]=y; for(int i=1;i<=c;i++) LCT[i].pushup(x); } else if(fl==1){ int x=read(),y=read(),col2=read()+1; if(x>y) swap(x,y); int col1=mp[m_p(x,y)]; if(col1==0){ puts("No such edge."); continue; } if(col1==col2){ puts("Success."); continue; } if(color[x][col2]==2||color[y][col2]==2){ puts("Error 1."); continue; } if(LCT[col2].findroot(x)==LCT[col2].findroot(y)){ puts("Error 2."); continue; } puts("Success."); LCT[col1].cut(x,y); mp[m_p(x,y)]=col2; color[x][col1]--;color[y][col1]--; color[x][col2]++;color[y][col2]++; LCT[col2].link(x,y); } else { int col=read()+1,x=read(),y=read(); if(LCT[col].findroot(x)!=LCT[col].findroot(y)) puts("-1"); else { LCT[col].split(x,y); printf("%d\n", LCT[col].mx[y]); } } } }