题意:给你一棵树,每个节点有一个值,3种操作
1)Q u询问 某一个点的值。
2)I u v w 把u,v之间(包括u,v)所有的点的值都加上 w
3) D u v w 把u,v之间(包括u,v)所有的点的值都减去 w
解题思路:树链剖分,树状数组记录改变值要比线段树快一点。
解题代码:
1 // File Name: 3966.2.cpp 2 #pragma comment(linker, "/STACK:1024000000,1024000000") 3 // Author: darkdream 4 // Created Time: 2015年04月14日 星期二 11时01分25秒 5 6 #include<vector> 7 #include<list> 8 #include<map> 9 #include<set> 10 #include<deque> 11 #include<stack> 12 #include<bitset> 13 #include<algorithm> 14 #include<functional> 15 #include<numeric> 16 #include<utility> 17 #include<sstream> 18 #include<iostream> 19 #include<iomanip> 20 #include<cstdio> 21 #include<cmath> 22 #include<cstdlib> 23 #include<cstring> 24 #include<ctime> 25 #define LL long long 26 #define maxn 50005 27 using namespace std; 28 int sz[maxn]; 29 int fa[maxn]; 30 int son[maxn]; 31 int top[maxn]; 32 int dep[maxn]; 33 int w[maxn]; 34 int totw; 35 vector<int> mp[maxn]; 36 int tr[maxn]; 37 int val[maxn]; 38 int lowbit(int x) 39 { 40 return x & -x; 41 } 42 int n; 43 void update(int x, int uv){ 44 //printf("%d %d\n",x,uv); 45 while(x <= n + 1){ 46 tr[x] += uv; 47 x += lowbit(x); 48 } 49 } 50 int getsum(int x){ 51 int sum = 0 ; 52 while(x >= 1) 53 { 54 sum += tr[x]; 55 x -= lowbit(x); 56 } 57 return sum ; 58 } 59 60 void dfs_1(int k,int la,int d){ 61 int num = mp[k].size(); 62 dep[k] = d; 63 fa[k] = la ; 64 sz[k] = 1; 65 son[k] = -1; 66 for(int i = 0 ;i < num ;i ++){ 67 if(mp[k][i] != la){ 68 dfs_1(mp[k][i],k,d+1); 69 sz[k] += sz[mp[k][i]]; 70 if(son[k] == -1 || sz[mp[k][i]] > sz[son[k]]) 71 son[k] = mp[k][i]; 72 } 73 } 74 } 75 void dfs_2(int k ,int sp) 76 { 77 top[k] = sp ; 78 if(son[k] != -1){ 79 w[k] = ++ totw ; 80 dfs_2(son[k],sp); 81 }else{ 82 w[k] = ++totw; 83 return ; 84 } 85 int num = mp[k].size(); 86 for(int i = 0 ;i < num ;i ++){ 87 if(mp[k][i] != son[k] && mp[k][i] != fa[k]){ 88 dfs_2(mp[k][i],mp[k][i]); 89 } 90 } 91 } 92 void make(){ 93 totw = 0 ; 94 memset(tr,0,sizeof(tr)); 95 dfs_1(1,0,1); 96 dfs_2(1,1); 97 } 98 void find(int u ,int v, int uv){ 99 int f1 = top[u],f2= top[v]; 100 int tmp = 0 ; 101 while(f1 != f2){ 102 if(dep[f1] < dep[f2]) 103 { 104 swap(u,v); 105 swap(f1,f2); 106 } 107 update(w[f1],uv); 108 update(w[u]+1,-uv); 109 u = fa[f1]; 110 f1 = top[u]; 111 } 112 if(dep[u] > dep[v]){ 113 swap(u,v); 114 } 115 update(w[u],uv); 116 update(w[v]+1,-uv); 117 }//不停的更新u,v,一直到在同一条链上 118 int main(){ 119 int m , q; 120 while(scanf("%d %d %d",&n,&m,&q) != EOF){ 121 for(int i = 1;i <= n;i ++) 122 mp[i].clear(); 123 for(int i = 1;i <= n;i ++) 124 scanf("%d",&val[i]); 125 int u,v; 126 for(int i = 1;i < n;i ++){ 127 scanf("%d %d",&u,&v); 128 mp[v].push_back(u); 129 mp[u].push_back(v); 130 } 131 make(); 132 char op[10]; 133 while(q--) 134 { 135 scanf("%s",op); 136 if(op[0] == 'Q'){ 137 scanf("%d",&v); 138 printf("%d\n",val[v] + getsum(w[v])); 139 continue; 140 } 141 int add; 142 scanf("%d %d %d",&u,&v,&add); 143 if(op[0] == 'I') 144 find(u,v,add); 145 else find(u,v,-add); 146 } 147 } 148 return 0; 149 }
没有梦想,何谈远方