hdu4010-Query on The Trees(lct分裂合并加值查询最大值)
代码
#include<cstdio> #include<cstring> #include<string> #include<vector> #include<algorithm> using namespace std; const int INF=1e9+7; const int maxn=300005; int val[maxn]; int N,Q; vector<int> G[maxn]; struct lct { lct *fa,*son[2]; int rev,v,mv,add; }; struct LCT { lct data[maxn]; lct *null; void init(int Size=maxn-1) //初始化 { null=data; //null指向首元素 for(int i=0;i<=Size;i++) { data[i].son[0]=data[i].son[1]=data[i].fa=null; data[i].v=data[i].mv=val[i]; data[i].rev=data[i].add=0; } null->v=null->mv=-INF; } void dfs(int u,int fa) { data[u].fa=data+fa; int Size=G[u].size(); for(int i=0;i<Size;i++) { int v=G[u][i]; if(v==fa) continue; dfs(v,u); } } void push_add(lct* x,int add) { if(x==null) return; x->v+=add; x->add+=add; x->mv+=add; } void push_rev(lct* x) { if(x==null) return; x->rev=!x->rev; swap(x->son[0],x->son[1]); } void pushdown(lct* x) { if(x->add!=0) { push_add(x->son[0],x->add); push_add(x->son[1],x->add); x->add=0; } if(x->rev) { push_rev(x->son[0]); push_rev(x->son[1]); x->rev=0; } } void pushup(lct* x) { if(x==null) return; x->mv=x->v; x->mv=max(x->mv,x->son[0]->mv); x->mv=max(x->mv,x->son[1]->mv); } bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里 { return (y=x->fa)!=null&&(y->son[0]==x||y->son[1]==x); } void Rotate(lct* x,int d) //翻转 { lct* y=x->fa; //x的父亲 y->son[d^1]=x->son[d]; if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y x->fa=y->fa; //连接 if(y->fa->son[0]==y) x->fa->son[0]=x; else if(y->fa->son[1]==y) x->fa->son[1]=x; x->son[d]=y; y->fa=x; } void Splay(lct* x) { pushdown(x); //清除标记 lct* y; while(Same(x,y)) //没有到树的最顶点 { pushdown(y); pushdown(x); Rotate(x,y->son[0]==x); //翻转 pushup(y); pushup(x); } } lct* Access(lct* u) //打通路径,返回的是根 { lct *v=null; for(;u!=null;u=u->fa) { Splay(u); u->son[1]=v; pushup(v=u); } return v; } lct* GetRoot(lct* x) //得到根 { for(x=Access(x);pushdown(x),x->son[0]!=null;x=x->son[0]) pushup(x); return x; } void MakeRoot(lct* x) //使x成为根 { Access(x); Splay(x); push_rev(x); } void Link(lct* x,lct* y) //连接两个点 { MakeRoot(x); x->fa=y; Access(x); } void Cut(lct* x,lct* y) //断开两个点 { MakeRoot(x); Access(y); Splay(y); y->son[0]->fa=null; y->son[0]=null; } void Add(lct* x,lct* y,int add) { MakeRoot(x); push_add(Access(y),add); } int MaxVal(lct* x,lct* y) { MakeRoot(x); Access(y); Splay(y); return y->mv; } }A; int main() { while(scanf("%d",&N)!=EOF) { for(int i=0;i<=N;i++) G[i].clear(); int x,y; for(int i=1;i<N;i++) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } val[0]=0; for(int i=1;i<=N;i++) scanf("%d",&val[i]); A.init(N); A.dfs(1,0); int type,w; scanf("%d",&Q); while(Q--) { scanf("%d",&type); if(type==3) scanf("%d",&w); scanf("%d%d",&x,&y); bool same=(A.GetRoot(A.data+x)==A.GetRoot(A.data+y)); if(type==1) { if(same) printf("-1\n"); else A.Link(A.data+x,A.data+y); } else if(type==2) { if(x==y||!same) printf("-1\n"); else A.Cut(A.data+x,A.data+y); } else if(type==3) { if(!same) printf("-1\n"); else A.Add(A.data+x,A.data+y,w); } else { if(!same) printf("-1\n"); else printf("%d\n",A.MaxVal(A.data+x,A.data+y)); } } printf("\n"); } return 0; }