如果$c=0$(也就是只有一种颜色),那么开一个LCT,再维护一下结点度即可;那么现在$c<10$,考虑开$c+1$棵LCT,一起维护。边查找直接上map就可以了。
#include<cstdio> #include<map> using namespace std; const int N=10005; char rB[1<<21],*rS,*rT; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } int val[N],st[N],sl; struct edge{ int u,v; edge(){} edge(int x,int y){ if(x<y){u=x;v=y;} else{u=y;v=x;} } inline bool operator <(const edge &b)const{return u<b.u||u==b.u&&v<b.v;} }; map<edge,int> f; struct LCT{ int maxn[N],f[N],ch[N][2],d[N]; bool tag[N]; inline bool nrt(int o){return ch[f[o]][0]==o||ch[f[o]][1]==o;} inline bool dir(int o){return ch[f[o]][1]==o;} inline void flip(int o){ if(o){ int t=ch[o][0];ch[o][0]=ch[o][1];ch[o][1]=t; tag[o]^=1; } } inline void pushup(int o){ maxn[o]=maxn[ch[o][0]]>maxn[ch[o][1]]?maxn[ch[o][0]]:maxn[ch[o][1]]; if(val[o]>maxn[o])maxn[o]=val[o]; } inline void pushd(int o){ if(tag[o]){ flip(ch[o][0]);flip(ch[o][1]); tag[o]=0; } } inline void rot(int o){ int fa=f[o]; bool d=dir(o); f[o]=f[fa]; if(nrt(fa))ch[f[fa]][dir(fa)]=o; if(ch[fa][d]=ch[o][d^1])f[ch[fa][d]]=fa; f[ch[o][d^1]=fa]=o; pushup(fa); } inline void splay(int o){ int k=st[sl=0]=o; while(nrt(k)){k=f[k];st[++sl]=k;} while(sl>=0)pushd(st[sl--]); for(;nrt(o);rot(o))if(nrt(f[o]))rot((dir(o)^dir(f[o]))?o:f[o]); pushup(o); } inline void access(int x){ for(int y=0;x;x=f[y=x]){ splay(x); ch[x][1]=y; pushup(x); } } inline int findrt(int x){ access(x);splay(x); for(pushd(x);ch[x][0];pushd(x))x=ch[x][0]; splay(x); return x; } inline void makert(int x){ access(x);splay(x); flip(x); } inline void link(int x,int y){ makert(x); ++d[x];++d[y]; f[x]=y; } inline void cut(int x,int y){ makert(x);access(y);splay(x); --d[x];--d[y]; ch[x][1]=f[y]=0; pushup(x); } }lct[10]; int main(){ int n=rd(),m=rd(),c=rd(),q=rd(),i,j,u,v,w,p,opt; for(i=1;i<=n;++i){ val[i]=rd(); for(j=0;j<c;++j)lct[j].maxn[i]=val[i]; } while(m--){ u=rd();v=rd();w=rd(); lct[w].link(u,v); f[edge(u,v)]=w; } while(q--){ opt=rd();u=rd();v=rd(); if(!opt){ val[u]=v; for(i=0;i<c;++i)lct[i].splay(u); }else if(opt==1){ w=rd(); if(f.find(edge(u,v))==f.end()){puts("No such edge.");continue;} //用find或者count,不要用[] p=f[edge(u,v)]; if(w==p){puts("Success.");continue;} if(lct[w].d[u]>=2||lct[w].d[v]>=2){puts("Error 1.");continue;} lct[w].makert(u); if(lct[w].findrt(v)==u){puts("Error 2.");continue;} puts("Success."); lct[p].cut(u,v);lct[w].link(u,v); f[edge(u,v)]=w; }else if(opt==2){ lct[u].makert(v); if(lct[u].findrt(w=rd())!=v)puts("-1"); else printf("%d\n",lct[u].maxn[v]); } } return 0; }