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 MB
Submit: 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

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

Sample Output

4
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
",Q_max(u,v));
233             }
234             else
235             {
236                 int u,v;
237                 read(u); read(v);
238                 printf("%d
",Q_sum(u,v));
239             }
240         }
241     }
242     return 0;
243 }
View Code
原文地址:https://www.cnblogs.com/Sunnie69/p/5460753.html