1. 程式人生 > >LCT--luogu P2173 [ZJOI2012]網路

LCT--luogu P2173 [ZJOI2012]網路

傳送門

L C T LCT 裸題,開 c c l

c t lct 就好了
板子還是不太熟 q w q qwq

不過這道題的修改邊的操作還是比較有意思的
一開始寫的複雜而且還不太對,改了之後就 A

A

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10005
#define M 100005
#define C 12
#define ls ch[c][x][0]
#define rs ch[c][x][1]
#define fa f[c][x]
#define int long long
using
namespace std; inline int rd(){ int x=0,f=1;char c=' '; while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar(); while(c<='9' && c>='0') x=x*10+c-'0',c=getchar(); return x*f; } inline int max(int x,int y){return x>y?x:y;} namespace lct{ int f[C][N],ch[C][N][2],rev[C][N],sum[C][N],val[N],d[C][N]; inline int get(int c,int x){return ch[c][fa][1]==x;} inline void update(int c,int x) {sum[c][x]=max(sum[c][ls],max(val[x],sum[c][rs]));} inline int isrt(int c,int x) {return ch[c][fa][0]!=x && ch[c][fa][1]!=x;} inline void rever(int c,int x){rev[c][x]^=1;swap(ls,rs);} inline void pushdown(int c,int x){ if(rev[c][x]){ if(ls) rever(c,ls); if(rs) rever(c,rs); rev[c][x]=0; } } void pushup(int c,int x){ if(!isrt(c,x)) pushup(c,fa); pushdown(c,x); } inline void rotate(int c,int x){ int old=f[c][x],oldf=f[c][old],wh=get(c,x); if(!isrt(c,old)) ch[c][oldf][get(c,old)]=x; f[c][x]=oldf; f[c][ch[c][x][wh^1]]=old; ch[c][old][wh]=ch[c][x][wh^1]; ch[c][x][wh^1]=old; f[c][old]=x; update(c,old); update(c,x); } inline void splay(int c,int x){ pushup(c,x);// for(;!isrt(c,x);rotate(c,x)) if(!isrt(c,fa)) rotate(c,get(c,x)==get(c,fa)?fa:x); } inline void access(int c,int x){ for(int y=0;x;y=x,x=fa) splay(c,x),rs=y,update(c,x); } inline void makeroot(int c,int x){ access(c,x); splay(c,x); rever(c,x); } inline int findroot(int c,int x){ access(c,x); splay(c,x); while(ls) pushdown(c,x),x=ls;//pushdown return x; } inline void split(int c,int x,int y){ makeroot(c,x); access(c,y); splay(c,y); } inline void link(int c,int x,int y){ d[c][x]++; d[c][y]++; makeroot(c,x); f[c][x]=y; splay(c,x); } inline bool check(int c,int x,int y){ return ch[c][y][0]==x && !rs; } inline void cut(int c,int x,int y){ split(c,x,y); if(check(c,x,y)){ d[c][x]--; d[c][y]--; fa=ch[c][y][0]=0,update(c,y); } } }using lct::findroot; int n,m,c,q; inline void solve(int x,int y,int z){ for(int i=0;i<c;i++){ lct::split(i,x,y); if(!lct::check(i,x,y)) continue; if(i==z) {puts("Success.");return;} if(lct::d[z][x]>1 || lct::d[z][y]>1){ puts("Error 1."); return; } if(findroot(z,x)==findroot(z,y)){ puts("Error 2."); return; } lct::cut(i,x,y); lct::link(z,x,y); puts("Success."); return; } puts("No such edge."); return; } int x,y,z,opt; signed main(){ n=rd(); m=rd(); c=rd(); q=rd(); for(int i=1;i<=n;i++) lct::val[i]=rd(); for(int i=1;i<=m;i++){ x=rd(),y=rd(),z=rd(); if(findroot(z,x)!=findroot(z,y)) lct::link(z,x,y); } while(q--){ opt=rd(); if(opt==0){ x=rd(),y=rd(); lct::val[x]=y; for(int i=0;i<c;i++){ lct::access(i,x); lct::splay(i,x); lct::update(i,x); } } if(opt==1){ x=rd(),y=rd(),z=rd(); solve(x,y,z); } if(opt==2){ x=rd(),y=rd(),z=rd(); lct::split(x,y,z); if(findroot(x,y)!=findroot(x,z)) puts("-1"); else printf("%lld\n",lct::sum[x][z]); } } return 0; }