1 5 1 2 3 4 5 1 2 2 3 3 4 4 5 5 1 5 1 5 1 1 1 1 2 5 1 1 1 2 1
4 0 0 1 0
splay维护路径上的最大值max,最小值min,
以及从左到右能得到的最大利益l,从右到左能得到的最大利益r
举例:
根的最大值=max(左孩子最大值,自己的值,右孩子最大值)
根从左到右的最大值=max(左孩子的左到右最大值,右孩子的左到右最大值,max(右孩子最大值,根)-min(根,左孩子最小值))
在be_root的时候,要记得把r,l反转即可
time:2031ms
#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define maxn 500007 #define inf 1000000000 struct Node{ Node *fa,*ch[2]; bool rev,root; int val,add,max,min,l,r; }; Node pool[maxn]; Node *nil,*tree[maxn]; int cnt = 0; void init(){ cnt = 1; nil = tree[0] = pool; nil -> l = 0; nil -> r = 0; nil -> max = -inf; nil -> min = inf; } 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].max = val; pool[cnt].min = val; pool[cnt].l = 0; pool[cnt].r = 0; return &pool[cnt++]; } //splay向上更新信息 void update(Node *x){ x->max = x->min = x->val; if(x->ch[0] != nil){ x->max < x->ch[0]->max?x->max=x->ch[0]->max:0; x->min > x->ch[0]->min?x->min=x->ch[0]->min:0; } if(x->ch[1] != nil){ x->max < x->ch[1]->max?x->max=x->ch[1]->max:0; x->min > x->ch[1]->min?x->min=x->ch[1]->min:0; } x->l = x->ch[1]->l < x->ch[0]->l?x->ch[0]->l:x->ch[1]->l; x->l = max(x->l,max(x->ch[1]->max,x->val) -min(x->ch[0]->min,x->val)); x->r = x->ch[1]->r < x->ch[0]->r?x->ch[0]->r:x->ch[1]->r; x->r = max(x->r,max(x->ch[0]->max,x->val) -min(x->ch[1]->min,x->val)); } void update_rev(Node *x){ if(x == nil) return ; x->rev = !x->rev; swap(x->ch[0],x->ch[1]); swap(x->l,x->r); } void update_add(Node *x,int n){ if(x == nil) return ; x->max += n ; x->min += 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); } 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 t,n,w,x,y,v,q; Node*p; scanf("%d",&t); while(t--){ scanf("%d",&n); memset(head,-1,sizeof(head)); ecnt = 0; init(); for(int i = 1;i <= n; i++) scanf("%d",&value[i]); for(int i = 1; i < n; i++){ scanf("%d%d",&x,&y); add_edge(x,y); } dfs(1,0); scanf("%d",&q); while(q--){ scanf("%d%d%d",&x,&y,&w); be_root(tree[x]); p = access(tree[y]); printf("%d\n",p->l); update_add(p,w); } } return 0; }