Solution
- 对于每个颜色建一棵 LCT
- 由于两点间至多有一条边,可用 map 维护两点间边的颜色
- 0 操作把每颗颜色的 LCT 上 x Splay 到 顶点,改颜色
- 1 操作先依次判断,再断原来的边,连边
- 2 操作在对应颜色的 LCT 内将 u 至 v 的路径提取出来,输出维护的最大值
Code
#include <cstdio> #include <cstdlib> #include <map> #include <algorithm> #define ll long long using namespace std; const int N=1e5+10; int n,m,k,c,u,v,w,col[10010][11],opt; int rev[N],ch[N][2],fa[N],val[N],ma[N],st[N]; map <ll,int> dict; bool nroot(int x) { return x==ch[fa[x]][0]||x==ch[fa[x]][1]; } int get(int x) { return x==ch[fa[x]][1]; } void push_up(int x) { ma[x]=val[x]; if(ch[x][0]) ma[x]=max(ma[x],ma[ch[x][0]]); if(ch[x][1]) ma[x]=max(ma[x],ma[ch[x][1]]); } void change(int x) { if(!x) return ; swap(ch[x][0],ch[x][1]); rev[x]^=1; } void push_down(int x) { if(!rev[x]) return ; change(ch[x][0]),change(ch[x][1]); rev[x]=0; } void rotate(int x) { int y=fa[x],z=fa[y],wh=get(x); if(nroot(y)) ch[z][get(y)]=x; if(ch[x][!wh]) fa[ch[x][!wh]]=y; ch[y][wh]=ch[x][!wh]; ch[x][!wh]=y; fa[y]=x,fa[x]=z; push_up(y),push_up(x); } void splay(int x) { st[++st[0]]=x; for(int i=x;nroot(i);i=fa[i]) st[++st[0]]=fa[i]; for(;st[0];st[0]--) push_down(st[st[0]]); for(int fx;fx=fa[x],nroot(x);rotate(x)) if(nroot(fx)) rotate(get(x)==get(fx)?fx:x); } void access(int x) { for(int y=0;x;x=fa[y=x]) splay(x),ch[x][1]=y,push_up(x); } void makeroot(int x) { access(x); splay(x); change(x); } int findroot(int x) { access(x); splay(x); while(ch[x][0]) push_down(x),x=ch[x][0]; splay(x); return x; } int link(int x,int y) { makeroot(x); if(findroot(y)!=x) fa[x]=y; else return 0; return 1; } void cut(int x,int y) { makeroot(x); if(findroot(y)==x && fa[y]==x && !ch[y][0]) fa[y]=ch[x][1]=0; } int split(int x,int y) { makeroot(x); access(y); splay(y); return y; } int main() { scanf("%d%d%d%d",&n,&m,&c,&k); for(int i=1;i<=n;i++) { scanf("%d",&val[i]); for(int j=1;j<c;j++) val[j*n+i]=val[i]; } for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&w); w++; if(u>v) swap(u,v); col[u][w]++,col[v][w]++; link((w-1)*n+u,(w-1)*n+v); ll x=u; x*=n,x+=v; dict[x]=w; } while(k--) { scanf("%d%d%d",&opt,&u,&v); if(!opt) { for(int i=0;i<c;i++) { int x=i*n+u; splay(x),val[x]=v,push_up(x); } continue; } scanf("%d",&w); if(opt==1) { w++; if(u>v) swap(u,v); ll x=u; x*=n,x+=v; if(!dict.count(x)) { puts("No such edge."); continue; } if(dict[x]==w) { puts("Success."); continue; } if(col[u][w]>1 || col[v][w]>1) { puts("Error 1."); continue; } if(link(u+n*(w-1),v+n*(w-1))) col[u][w]++,col[v][w]++; else { puts("Error 2."); continue; } int pre=dict[x]; cut(u+n*(pre-1),v+n*(pre-1)); col[u][pre]--,col[v][pre]--; dict[x]=w; puts("Success."); } else { u++; int x=v+n*(u-1),y=w+n*(u-1); makeroot(x); if(findroot(y)!=x) puts("-1"); else printf("%d\n",ma[split(x,y)]); } } return 0; }
来源:https://www.cnblogs.com/hsez-cyx/p/12393712.html