2014-10-05 16:30:43
思路:权在点上的线段树,加上树链剖分即可。注意这题容易RE爆栈,要手动扩栈!
1 /************************************************************************* 2 > File Name: 3966.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 05 Oct 2014 01:20:20 PM CST 6 ************************************************************************/ 7 #pragma comment(linker,"/STACK:1024000000,1024000000") 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 #define lp (p << 1) 15 #define rp (p << 1|1) 16 #define getmid(l,r) (l + (r - l) / 2) 17 const int maxn = 50010; 18 19 int N,M,P; 20 int A[maxn]; 21 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt; 22 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn],w[maxn],aw[maxn],tsz; 23 24 struct node{ 25 int add; 26 int val; 27 }t[maxn << 2]; 28 29 void Add_edge(int u,int v){ 30 next[++ecnt] = first[u]; 31 ver[ecnt] = v; 32 first[u] = ecnt; 33 } 34 35 void Dfs(int p,int pre,int d){ 36 sz[p] = 1; 37 dep[p] = d; 38 fa[p] = pre; 39 son[p] = -1; 40 int v,tmp = 0; 41 for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){ 42 Dfs(v,p,d + 1); 43 if(sz[v] > tmp){ 44 son[p] = v; 45 tmp = sz[v]; 46 } 47 sz[p] += sz[v]; 48 } 49 } 50 51 void Dfs_pos(int p,int tp){ 52 w[p] = ++tsz; 53 aw[tsz] = p; 54 top[p] = tp; 55 if(son[p] != -1) Dfs_pos(son[p],tp); 56 for(int i = first[p]; i != -1; i = next[i]){ 57 int v = ver[i]; 58 if(v != son[p] && v != fa[p]) 59 Dfs_pos(v,v); 60 } 61 } 62 63 void Build_tree(int p,int l,int r){ 64 t[p].add = 0; 65 if(l == r){ 66 t[p].val = A[aw[l]]; 67 return; 68 } 69 int mid = getmid(l,r); 70 Build_tree(lp,l,mid); 71 Build_tree(rp,mid + 1,r); 72 } 73 74 void Update_tree(int a,int b,int c,int p,int l,int r){ 75 if(a <= l && r <= b){ 76 t[p].add += c; 77 return; 78 } 79 int mid = getmid(l,r); 80 if(a <= mid) Update_tree(a,b,c,lp,l,mid); 81 if(b > mid) Update_tree(a,b,c,rp,mid + 1,r); 82 } 83 84 int Query_tree(int a,int p,int l,int r,int plu){ 85 if(l == r) 86 return t[p].val + t[p].add + plu; 87 int mid = getmid(l,r); 88 if(a <= mid) return Query_tree(a,lp,l,mid,plu + t[p].add); 89 else return Query_tree(a,rp,mid + 1,r,plu + t[p].add); 90 } 91 92 void Change(int a,int b,int c){ 93 int f1 = top[a],f2 = top[b]; 94 while(f1 != f2){ 95 if(dep[f1] > dep[f2]){ 96 swap(a,b); 97 swap(f1,f2); 98 } 99 Update_tree(w[f2],w[b],c,1,1,tsz); 100 b = fa[f2]; 101 f2 = top[b]; 102 } 103 if(dep[a] > dep[b]) swap(a,b); 104 Update_tree(w[a],w[b],c,1,1,tsz); 105 } 106 107 void Init(){ 108 memset(first,-1,sizeof(first)); 109 ecnt = 0; 110 tsz = 0; 111 } 112 113 int main(){ 114 char s[5]; 115 int a,b,c; 116 while(scanf("%d%d%d",&N,&M,&P) != EOF){ 117 Init(); 118 for(int i = 1; i <= N; ++i) 119 scanf("%d",A + i); 120 for(int i = 1; i < N; ++i){ 121 scanf("%d%d",&a,&b); 122 Add_edge(a,b); 123 Add_edge(b,a); 124 } 125 Dfs(1,0,0); 126 Dfs_pos(1,1); 127 Build_tree(1,1,tsz); 128 for(int i = 1; i <= P; ++i){ 129 scanf("%s%d",s,&a); 130 if(s[0] == 'I' || s[0] == 'D'){ 131 scanf("%d%d",&b,&c); 132 if(s[0] == 'D') Change(a,b,-c); 133 else Change(a,b,c); 134 } 135 else printf("%d\n",Query_tree(w[a],1,1,tsz,0)); 136 } 137 } 138 return 0; 139 }