5 1 2 2 4 2 5 1 3 1 2 3 4 5 6 4 2 3 2 1 2 4 2 3 1 3 5 3 2 1 4 4 1 4
3 -1 7
link-cut树模板练习中,就是比较慢不知道怎么优化
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 300007 #define inf 1000000000 struct Node{ Node *fa,*ch[2]; bool rev,root; int val,add,size; int max; }; Node pool[maxn]; Node *nil,*tree[maxn]; int cnt = 0; void init(){ cnt = 1; nil = tree[0] = pool; nil->size = 0; } inline Node *newnode(int val,Node *f){ pool[cnt].fa = f; pool[cnt].ch[0] = pool[cnt].ch[1] = nil; pool[cnt].rev = false; pool[cnt].root = true; pool[cnt].val = val; pool[cnt].add = 0; pool[cnt].size = 1; pool[cnt].max = val; return &pool[cnt++]; } void update_rev(Node *x){ if(x == nil) return ; x->rev = !x->rev; swap(x->ch[0],x->ch[1]); } //splay向上更新信息 void update(Node *x){ x->size = x->ch[0]->size + x->ch[1]->size + 1; x->max=x->val; if(x->ch[0] != nil) if(x->max < x->ch[0]->max) x->max = x->ch[0]->max; if(x->ch[1] != nil) if(x->max < x->ch[1]->max) x->max = x->ch[1]->max; } void update_add(Node *x,int n){ if(x == nil) return ; x->max += n ; x->val += n; x->add += n; } //splay下推信息 void pushdown(Node *x){ if(x->add != 0){ update_add(x->ch[0],x->add); update_add(x->ch[1],x->add); x->add = 0; } if(x->rev != false){ update_rev(x->ch[0]); update_rev(x->ch[1]); x->rev = false; } } //splay在root-->x的路径下推信息 void push(Node *x){ if(!x->root) push(x->fa); pushdown(x); } //将结点x旋转至splay中父亲的位置 void rotate(Node *x){ Node *f = x->fa, *ff = f->fa; int t = (f->ch[1] == x); if(f->root) x->root = true, f->root = false; else ff->ch[ff->ch[1] == f] = x; x->fa = ff; f->ch[t] = x->ch[t^1]; x->ch[t^1]->fa = f; x->ch[t^1] = f; f->fa = x; update(f); } //将结点x旋转至x所在splay的根位置 void splay(Node *x){ push(x); Node *f, *ff; while(!x->root){ f = x->fa,ff = f->fa; if(!f->root) if((ff->ch[1] == f) && (f->ch[1] == x)) rotate(f); else rotate(x); rotate(x); } update(x); } //将x到树根的路径并成一条path Node *access(Node *x){ Node *y = nil; while(x != nil){ splay(x); x->ch[1]->root = true; (x->ch[1] = y)->root = false; update(x); y = x; x = x->fa; } return y; } //将结点x变成树根 void be_root(Node *x){ access(x); splay(x); update_rev(x); } //将x连接到结点f上 void link(Node *x, Node *f){ be_root(x); x->fa = f; } //将x,y分离 void cut(Node *x,Node *y){ be_root(x); access(x); splay(y); y->fa = nil; } Node *find_root(Node *p){ while(1){ pushdown(p); if(p->ch[0] != nil) p = p->ch[0]; else break; } return p; } Node *find_father(Node *p){ pushdown(p); if(p->ch[0] == nil) return nil; p = p->ch[0]; while(1){ pushdown(p); if(p->ch[1] != nil) p = p->ch[1]; else break; } return p; } struct Edge{ int v,next; }; Edge edge[2*maxn]; int head[maxn],ecnt; int value[maxn]; void add_edge(int u,int v){ edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; edge[ecnt].v = u; edge[ecnt].next = head[v]; head[v] = ecnt++; } void dfs(int u,int f){ tree[u] = newnode(value[u],tree[f]); for(int i = head[u]; i != -1;i = edge[i].next){ if(edge[i].v == f) continue; dfs(edge[i].v,u); } } int main(){ int n,m,u,v,w,t,x,y; Node *p; while(scanf("%d",&n)!=EOF){ memset(head,-1,sizeof(head)); ecnt = 0; init(); for(int i = 0;i < n - 1; i++){ scanf("%d%d",&u,&v); add_edge(u,v); } for(int i = 1;i <= n; i++) scanf("%d",&value[i]); dfs(1,0); scanf("%d",&m); while(m--){ scanf("%d",&t); if(t == 1){ scanf("%d%d",&x,&y); be_root(tree[x]); p = access(tree[y]); if(tree[x] == find_root(p)) printf("-1\n"); else link(tree[x],tree[y]); } else if(t == 2){ scanf("%d%d",&x,&y); be_root(tree[x]); p = access(tree[y]); if(tree[x] != find_root(p) || y == x) printf("-1\n"); else { splay(tree[y]); p = find_father(tree[y]); cut(tree[y],p); } } else if(t == 3){ scanf("%d%d%d",&w,&x,&y); be_root(tree[x]); p = access(tree[y]); if(tree[x] != find_root(p)) printf("-1\n"); else update_add(p,w); } else { scanf("%d%d",&x,&y); be_root(tree[x]); p = access(tree[y]); if(tree[x] != find_root(p))printf("-1\n"); else printf("%d\n",p->max); } } printf("\n"); } return 0; }