BZOJ_1036_[ZJOI2008]_树的统计Conut_(树链剖分)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1036
给出一棵树以及各点的权值,对数进行如下三种操作:
1.改变某一节点u的值为t;
2.求节点u到节点v之间(包括u与v)的最大值;
3.求节点u到节点v之间(包括u与v)的和.
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12002 Solved: 4864
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
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
Sample Output
1
2
2
10
6
5
6
5
16
HINT
Source
分析
树链剖分模板题,但貌似LCA写得太原始了= =,并不会其他方法.直接裸的原始LCA好像可以过两个点...
注意:
1.对u,v进行操作时是判断tib[u]与tib[v]的大小,不然上线段树会炸.(tib[top[u]]<=tib[u]恒成立)
2.在LCA时别少写了dep[top[u]]==dep[top[v]]的情况.
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #define read(a) a=getnum() 6 #define lson (2*k) 7 #define rson (2*k+1) 8 #define mid ((a[k].l+a[k].r)>>1) 9 10 using namespace std; 11 12 const int maxn=30000+5,INF=30000+5; 13 14 struct node 15 { 16 int l,r,k,x,m; 17 }; 18 19 int n,q; 20 int label; 21 int w[maxn]; 22 int fa[maxn]; 23 int dep[maxn]; 24 int size[maxn]; 25 int son[maxn]; 26 int top[maxn]; 27 int tib[maxn]; 28 int rev_tib[maxn]; 29 bool vis1[maxn]; 30 bool vis2[maxn]; 31 vector <int> g1[maxn]; 32 vector <int> g2[maxn]; 33 node a[3*maxn]; 34 35 inline int getnum() 36 { 37 int r=0,k=1; 38 char c; 39 for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') k=-1; 40 for(;c>='0'&&c<='9';c=getchar()) r=r*10+c-'0'; 41 return r*k; 42 } 43 44 void build_tree(int l,int r,int k) 45 { 46 a[k].l=l; a[k].r=r; 47 if(l==r) 48 { 49 a[k].x=a[k].m=w[rev_tib[l]]; 50 return; 51 } 52 build_tree(l,mid,lson); 53 build_tree(mid+1,r,rson); 54 a[k].x=a[lson].x+a[rson].x; 55 a[k].m=max(a[lson].m,a[rson].m); 56 } 57 58 void update(int x,int t,int k) 59 { 60 if(a[k].l==a[k].r&&a[k].l==x) 61 { 62 a[k].x=a[k].m=t; 63 return; 64 } 65 if(x<=mid) update(x,t,lson); 66 else update(x,t,rson); 67 a[k].x=a[lson].x+a[rson].x; 68 a[k].m=max(a[lson].m,a[rson].m); 69 } 70 71 int get_max(int l,int r,int k) 72 { 73 if(l==a[k].l&&r==a[k].r) 74 { 75 return a[k].m; 76 } 77 if(r<=mid) return get_max(l,r,lson); 78 else if(l>mid) return get_max(l,r,rson); 79 else return max(get_max(l,mid,lson),get_max(mid+1,r,rson)); 80 } 81 82 int get_sum(int l,int r,int k) 83 { 84 if(l==a[k].l&&r==a[k].r) 85 { 86 return a[k].x; 87 } 88 if(r<=mid) return get_sum(l,r,lson); 89 else if(l>mid) return get_sum(l,r,rson); 90 else return get_sum(l,mid,lson)+get_sum(mid+1,r,rson); 91 } 92 93 94 void find_h_e(int u,int father,int depth) 95 { 96 vis1[u]=true; 97 fa[u]=father; 98 dep[u]=depth; 99 size[u]=1; 100 son[u]=0; 101 int max_size=0; 102 for(int i=0;i<g1[u].size();i++) 103 { 104 int v=g1[u][i]; 105 if(vis1[v]) continue; 106 g2[u].push_back(v); 107 find_h_e(v,u,depth+1); 108 size[u]+=size[v]; 109 if(size[v]>max_size) 110 { 111 max_size=size[v]; 112 son[u]=v; 113 } 114 } 115 } 116 117 void conect_h_e(int u,int ancestor) 118 { 119 vis2[u]=true; 120 top[u]=ancestor; 121 tib[u]=++label; 122 rev_tib[label]=u; 123 if(son[u]) 124 { 125 conect_h_e(son[u],ancestor); 126 } 127 for(int i=0;i<g2[u].size();i++) 128 { 129 int v=g2[u][i]; 130 if(vis2[v]) continue; 131 conect_h_e(v,v); 132 } 133 } 134 135 void Change(int u,int t) 136 { 137 update(tib[u],t,1); 138 } 139 140 int Q_max(int u,int v) 141 { 142 int max_now=-INF; 143 while(top[u]!=top[v]) 144 { 145 if(dep[top[u]]==dep[top[v]]) 146 { 147 max_now=max(max_now,get_max(tib[top[u]],tib[u],1)); 148 u=fa[top[u]]; 149 continue; 150 } 151 while(dep[top[u]]>dep[top[v]]) 152 { 153 max_now=max(max_now,get_max(tib[top[u]],tib[u],1)); 154 u=fa[top[u]]; 155 } 156 while(dep[top[u]]<dep[top[v]]) 157 { 158 max_now=max(max_now,get_max(tib[top[v]],tib[v],1)); 159 v=fa[top[v]]; 160 } 161 } 162 max_now=max(max_now,get_max(min(tib[v],tib[u]),max(tib[u],tib[v]),1)); 163 return max_now; 164 } 165 166 int Q_sum(int u,int v) 167 { 168 int sum_now=0; 169 while(top[u]!=top[v]) 170 { 171 if(dep[top[u]]==dep[top[v]]) 172 { 173 sum_now+=get_sum(tib[top[u]],tib[u],1); 174 u=fa[top[u]]; 175 continue; 176 } 177 while(dep[top[u]]>dep[top[v]]) 178 { 179 sum_now+=get_sum(tib[top[u]],tib[u],1); 180 u=fa[top[u]]; 181 } 182 while(dep[top[u]]<dep[top[v]]) 183 { 184 sum_now+=get_sum(tib[top[v]],tib[v],1); 185 v=fa[top[v]]; 186 } 187 } 188 sum_now+=get_sum(min(tib[v],tib[u]),max(tib[u],tib[v]),1); 189 return sum_now; 190 } 191 192 void init() 193 { 194 read(n); 195 for(int i=1;i<n;i++) 196 { 197 int u,v; 198 read(u); read(v); 199 g1[u].push_back(v); 200 g1[v].push_back(u); 201 } 202 for(int i=1;i<=n;i++) 203 { 204 read(w[i]); 205 } 206 } 207 208 int main() 209 { 210 init(); 211 read(q); 212 find_h_e(1,0,1); 213 conect_h_e(1,1); 214 build_tree(1,n,1); 215 for(int i=1;i<=q;i++) 216 { 217 char c; 218 c=getchar(); 219 if(c=='C') 220 { 221 int u,t; 222 read(u); read(t); 223 Change(u,t); 224 } 225 else 226 { 227 c=getchar(); 228 if(c=='M') 229 { 230 int u,v; 231 read(u); read(v); 232 printf("%d\n",Q_max(u,v)); 233 } 234 else 235 { 236 int u,v; 237 read(u); read(v); 238 printf("%d\n",Q_sum(u,v)); 239 } 240 } 241 } 242 return 0; 243 }