2014-10-08 21:43:43
思路:这题写了好久,一开始直接树链剖分,果断TLE。后来发现可以把加法树也转化为线性结构(核心思想),当然用树状数组也可以。
关于处理边的方法:把边的编号对应到它的较深点,形象的理解为边下沉一级。所以处理边时,在遍历树链时要格外注意。
1 /************************************************************************* 2 > File Name: 5044.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 06 Oct 2014 10:13:01 PM CST 6 ************************************************************************/ 7 8 #pragma comment(linker,"/STACK:1024000000,1024000000") 9 #include <cstdio> 10 #include <cstring> 11 #include <cstdlib> 12 #include <cmath> 13 #include <vector> 14 #include <map> 15 #include <set> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 100010; 27 28 int T,N,M; 29 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt; 30 int id[maxn << 1],aid[maxn]; 31 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn]; 32 int w[maxn],aw[maxn],tsz; 33 ll it1[maxn],it2[maxn],val1[maxn],val2[maxn]; 34 35 void Init(){ 36 memset(it1,0,sizeof(it1)); 37 memset(it2,0,sizeof(it2)); 38 memset(first,-1,sizeof(first)); 39 memset(val1,0,sizeof(val1)); 40 memset(val2,0,sizeof(val2)); 41 ecnt = 0; 42 tsz = 0; 43 } 44 45 inline int Read(){ 46 int x = 0,f = 1;char ch = getchar(); 47 while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();} 48 while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} 49 return x * f; 50 } 51 52 void Add_edge(int u,int v,int i){ 53 next[++ecnt] = first[u]; 54 ver[ecnt] = v; 55 id[ecnt] = i; 56 first[u] = ecnt; 57 next[++ecnt] = first[v]; 58 ver[ecnt] = u; 59 id[ecnt] = i; 60 first[v] = ecnt; 61 } 62 63 void Dfs(int p,int pre,int d){ 64 sz[p] = 1; 65 dep[p] = d; 66 son[p] = -1; 67 fa[p] = pre; 68 int v,tmp = 0; 69 for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){ 70 aid[v] = id[i]; 71 Dfs(v,p,d + 1); 72 if(sz[v] > tmp){ 73 tmp = sz[v]; 74 son[p] = v; 75 } 76 sz[p] += sz[v]; 77 } 78 } 79 80 void Dfs_pos(int p,int tp){ 81 w[p] = ++tsz; 82 aw[tsz] = p; 83 top[p] = tp; 84 if(son[p] != -1) Dfs_pos(son[p],tp); 85 for(int i = first[p]; i != -1; i = next[i]){ 86 int v = ver[i]; 87 if(v != son[p] && v != fa[p]) 88 Dfs_pos(v,v); 89 } 90 } 91 92 void Update1(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 it1[w[f2]] += c; 100 it1[w[b] + 1] -= c; 101 b = fa[f2]; 102 f2 = top[b]; 103 } 104 if(dep[a] > dep[b]) swap(a,b); 105 it1[w[a]] += c; 106 it1[w[b] + 1] -= c; 107 } 108 109 void Update2(int a,int b,int c){ 110 int f1 = top[a],f2 = top[b]; 111 while(f1 != f2){ 112 if(dep[f1] > dep[f2]){ 113 swap(a,b); 114 swap(f1,f2); 115 } 116 it2[w[f2]] += c; 117 it2[w[b] + 1] -= c; 118 b = fa[f2]; 119 f2 = top[b]; 120 } 121 if(dep[a] > dep[b]) swap(a,b); 122 it2[w[son[a]]] += c; 123 it2[w[b] + 1] -= c; 124 } 125 126 int main(){ 127 char s[10]; 128 int a,b,c; 129 T = Read(); 130 for(int Case = 1; Case <= T; ++Case){ 131 Init(); 132 N = Read(); 133 M = Read(); 134 for(int i = 1; i < N; ++i){ 135 a = Read(),b = Read(); 136 Add_edge(a,b,i); 137 } 138 Dfs(1,0,0); 139 Dfs_pos(1,1); 140 while(M--){ 141 scanf("%s",s); 142 a = Read(),b = Read(),c = Read(); 143 if(s[3] == '1'){ 144 Update1(a,b,c); 145 } 146 else{ 147 Update2(a,b,c); 148 } 149 } 150 printf("Case #%d:\n",Case); 151 it1[0] = it2[1] = 0; 152 for(int i = 1; i <= N; ++i){ 153 it1[i] += it1[i - 1]; 154 val1[aw[i]] = it1[i]; 155 } 156 for(int i = 2; i <= N; ++i){ 157 it2[i] += it2[i - 1]; 158 val2[aid[aw[i]]] = it2[i]; 159 } 160 for(int i = 1; i <= N; ++i){ 161 if(i != 1) printf(" "); 162 printf("%I64d",val1[i]); 163 } 164 puts(""); 165 if(N > 1){ 166 for(int i = 1; i < N; ++i){ 167 if(i != 1) printf(" "); 168 printf("%I64d",val2[i]); 169 } 170 } 171 puts(""); 172 } 173 return 0; 174 }