[ZJOI2008]樹的統計
阿新 • • 發佈:2020-08-28
題目描述
一棵樹上有nn個節點,編號分別為11到nn,每個節點都有一個權值ww。
我們將以下面的形式來要求你對這棵樹完成一些操作:
I.CHANGE u t
: 把結點uu的權值改為tt。
II.QMAX u v
: 詢問從點uu到點vv的路徑上的節點的最大權值。
III.QSUM u v
: 詢問從點uu到點vv的路徑上的節點的權值和。
注意:從點uu到點vv的路徑上的節點包括uu和vv本身。
輸入格式
輸入檔案的第一行為一個整數nn,表示節點的個數。
接下來n-1n−1行,每行22個整數aa和bb,表示節點aa和節點bb之間有一條邊相連。
接下來一行nn個整數,第ii個整數w_iwi表示節點ii的權值。
接下來11行,為一個整數qq,表示操作的總數。
接下來qq行,每行一個操作,以CHANGE u t
或者QMAX u v
或者QSUM u v
的形式給出。
輸出格式
對於每個QMAX
或者QSUM
的操作,每行輸出一個整數表示要求輸出的結果。
輸入輸出樣例
輸入4 1 2 2 3 4 1 4 2 1 3 12 QMAX 3 4 QMAX 3 3 QMAX 3 2 QMAX 2 3 QSUM 3 4 QSUM 2 1 CHANGE 1 5 QMAX 3 4 CHANGE 3 6 QMAX 3 4 QMAX 2 4 QSUM 3 4輸出
4 1 2 2 10 6 5 6 5 16
說明/提示
對於100 \%100%的資料,保證1\le n \le 3\times 10^41≤n≤3×104,0\le q\le 2\times 10^50≤q≤2×105。
中途操作中保證每個節點的權值ww在-3\times 10^4−3×104到3\times 10^43×104之間。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int head[100001],tot,n,q,w[100001],d[1000001],fa[1000001],size[1000001],sum,top[1000001],pos[10000001View Code]; 4 struct data { 5 int to,nxt; 6 } e[1000001]; 7 struct SegmentTree { 8 int sum,l,r,mx; 9 #define l(x) tree[x].l 10 #define r(x) tree[x].r 11 #define sum(x) tree[x].sum 12 #define mx(x) tree[x].mx 13 } tree[4000004]; 14 void add(int x,int y) { 15 e[++tot].to=y; 16 e[tot].nxt=head[x]; 17 head[x]=tot; 18 } 19 void build(int p,int l,int r) { 20 l(p)=l,r(p)=r; 21 if(l==r) 22 return; 23 int mid=l+r>>1; 24 build(p<<1,l,mid); 25 build(p<<1|1,mid+1,r); 26 } 27 void change(int p,int x,int v) { 28 if(l(p)==r(p)) { 29 sum(p)=v; 30 mx(p)=v; 31 return; 32 } 33 int mid=l(p)+r(p)>>1; 34 if(x<=mid) change(p<<1,x,v); 35 else change(p<<1|1,x,v); 36 mx(p)=max(mx(p<<1),mx(p<<1|1)); 37 sum(p)=sum(p<<1)+sum(p<<1|1); 38 } 39 int query_sum(int p,int l,int r) { 40 if(l<=l(p)&&r>=r(p)) 41 return sum(p); 42 int val=0; 43 int mid=l(p)+r(p)>>1; 44 if(l<=mid) val+=query_sum(p<<1,l,r); 45 if(r>mid) val+=query_sum(p<<1|1,l,r); 46 return val; 47 } 48 int query_mx(int p,int l,int r) { 49 if(l<=l(p)&&r>=r(p)) 50 return mx(p); 51 int val=-(1<<30); 52 int mid=l(p)+r(p)>>1; 53 if(l<=mid) val=max(val,query_mx(p<<1,l,r)); 54 if(r>mid) val=max(val,query_mx(p<<1|1,l,r)); 55 return val; 56 } 57 void dfs1(int x) { 58 size[x]=1; 59 for(int i=head[x]; i; i=e[i].nxt) { 60 int v=e[i].to; 61 if(v==fa[x]) continue; 62 fa[v]=x; 63 d[v]=d[x]+1; 64 dfs1(v); 65 size[x]+=size[v]; 66 } 67 } 68 void dfs2(int x,int t) { //jiedian top 69 int node=0; 70 pos[x]=++sum; 71 top[x]=t; 72 for(int i=head[x]; i; i=e[i].nxt) 73 if(d[e[i].to]>d[x]&&size[e[i].to]>size[node]) 74 node=e[i].to; 75 if(node==0) 76 return; 77 dfs2(node,t); 78 for(int i=head[x]; i; i=e[i].nxt) 79 if(d[e[i].to]>d[x]&&node!=e[i].to) 80 dfs2(e[i].to,e[i].to); 81 } 82 int solve_sum(int x,int y) { 83 int val=0; 84 while(top[x]!=top[y]) { 85 if(d[top[x]]<d[top[y]]) swap(x,y); 86 val+=query_sum(1,pos[top[x]],pos[x]); 87 x=fa[top[x]]; 88 } 89 if(pos[x]>pos[y]) swap(x,y); 90 val+=query_sum(1,pos[x],pos[y]); 91 return val; 92 } 93 int solve_mx(int x,int y) { 94 int val=-(1<<30); 95 while(top[x]!=top[y]) { 96 if(d[top[x]]<d[top[y]]) swap(x,y); 97 val=max(val,query_mx(1,pos[top[x]],pos[x])); 98 x=fa[top[x]]; 99 } 100 if(pos[x]>pos[y]) swap(x,y); 101 val=max(val,query_mx(1,pos[x],pos[y])); 102 return val; 103 } 104 void init() { 105 scanf("%d",&n); 106 for(int i=1,x,y; i<n; i++) 107 scanf("%d%d",&x,&y),add(x,y),add(y,x); 108 for(int i=1; i<=n; i++) 109 scanf("%d",&w[i]); 110 } 111 void solve() { 112 build(1,1,n); 113 for(int i=1; i<=n; i++) 114 change(1,pos[i],w[i]); 115 scanf("%d",&q); 116 for(int i=1; i<=q; i++) { 117 char c[10]; 118 int x,y; 119 scanf("%s%d%d",c,&x,&y); 120 if(c[0]=='C') 121 change(1,pos[x],y); 122 else { 123 if(c[1]=='M') 124 printf("%d\n",solve_mx(x,y)); 125 else 126 printf("%d\n",solve_sum(x,y)); 127 } 128 } 129 } 130 int main() { 131 init(); 132 dfs1(1); 133 dfs2(1,1); 134 solve(); 135 return 0; 136 }