P2590 [ZJOI2008]树的统计

Posted 2529102757ab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2590 [ZJOI2008]树的统计相关的知识,希望对你有一定的参考价值。

传送门

题目描述

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

注意:从点u到点v的路径上的节点包括u和v本身

输入输出格式

输入格式:

 

输入文件的第一行为一个整数n,表示节点的个数。

接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

接下来一行n个整数,第i个整数wi表示节点i的权值。

接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

 

输出格式:

 

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

 

输入输出样例

输入样例#1:
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
输出样例#1: 
4
1
2
2
10
6
5
6
5
16

说明

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。.

用一句话来形容,这是裸的!!!!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int maxn=1e5+10;
  8 struct node
  9 
 10     int next;
 11     int from;
 12     int to;
 13 way[maxn];
 14 int tot;
 15 int head[maxn];
 16 int size[maxn];
 17 int sumv[maxn<<2];
 18 int maxv[maxn<<2];
 19 int father[maxn];
 20 int top[maxn];
 21 int son[maxn];
 22 int a[maxn<<2];
 23 int deep[maxn];
 24 const int inf=1e9+10;
 25 int tuop[maxn];
 26 int n;
 27 int pre[maxn];
 28 int cnt=0;
 29 
 30 int add(int x,int y)
 31 
 32     way[++tot].next=head[x];
 33     way[tot].to=y;
 34     way[tot].from=x;
 35     head[x]=tot;
 36 
 37 
 38 void dfs1(int x,int fa)
 39 
 40     size[x]=1;
 41     for(int i=head[x];i;i=way[i].next)
 42     
 43         int to=way[i].to;
 44         if(to==fa)
 45         
 46             continue;
 47         
 48         deep[to]=deep[x]+1;
 49         father[to]=x;
 50         dfs1(to,x);
 51         size[x]+=size[to];
 52         if(size[to]>size[son[x]])
 53         
 54             son[x]=to;
 55         
 56     
 57 
 58 void dfs2(int x,int tp)
 59 
 60     top[x]=tp;
 61     tuop[x]=++cnt;
 62     pre[cnt]=x;
 63     if(son[x])
 64     
 65         dfs2(son[x],tp);
 66     
 67     for(int i=head[x];i;i=way[i].next)
 68     
 69         int to=way[i].to;
 70         if(to==father[x]||to==son[x])
 71         continue;
 72         dfs2(to,to);
 73     
 74 
 75 inline void pushup(int x)
 76 
 77     sumv[x]=sumv[x<<1]+sumv[(x<<1)^1];
 78     maxv[x]=max(maxv[x<<1],maxv[(x<<1)^1]);
 79 
 80 void build(int x,int l,int r)
 81 
 82     if(l==r)
 83     
 84         sumv[x]=maxv[x]=a[pre[l]];
 85         return ;
 86     
 87     int mid=(l+r)>>1;
 88     build(x<<1,l,mid);
 89     build((x<<1)^1,mid+1,r);
 90     pushup(x);
 91 
 92 void jia(int x,int l,int r,int q,int v)
 93 
 94     if(l==r)
 95     
 96         sumv[x]=maxv[x]=v;
 97         return ;
 98     
 99     int mid=(l+r)>>1;
100     if(q<=mid)
101     
102         jia(x<<1,l,mid,q,v);
103     
104     else
105     
106         jia((x<<1)^1,mid+1,r,q,v);
107     
108     pushup(x);
109 
110 int cha(int x,int l,int r,int ls,int rs)
111 
112     int ans=0;
113     if(ls<=l&&r<=rs)
114     
115         return sumv[x];
116     
117     int mid=(l+r)>>1;
118     if(ls<=mid)
119     
120         ans+=cha(x<<1,l,mid,ls,rs);
121     
122     if(rs>mid)
123     
124         ans+=cha((x<<1)^1,mid+1,r,ls,rs);
125     
126     pushup(x);
127     return ans;
128 
129 /*int chamax(int x,int l,int r,int ls,int rs)
130 
131     int ans=-inf;
132     if(ls<=l&&r<=rs)
133     
134         return maxv[x];
135     
136     int mid=(l+r)>>1;
137     if(ls<=mid)
138     
139         ans=max(ans,chamax(x<<1,l,mid,ls,rs));
140     
141     if(rs>mid)
142     
143         ans=max(ans,chamax((x<<1)^1,mid+1,r,ls,rs));
144     
145     pushup(x);
146     return ans;
147 */
148 int chamax(int o,int l,int r,int ql,int qr)
149     int mid=(l+r)/2,ans=-inf;
150     if (ql<=l&&r<=qr)return maxv[o];
151     if (ql<=mid)ans=max(ans,chamax(o*2,l,mid,ql,qr));
152     if (qr>mid)ans=max(ans,chamax(o*2+1,mid+1,r,ql,qr));
153     pushup(o);
154     return ans;
155 
156 int qsum(int x,int to)
157 
158     int ans=0;
159     while(top[x]!=top[to])
160     
161         if(deep[top[x]]<deep[top[to]])
162         
163             swap(x,to);
164         
165         ans+=cha(1,1,n,tuop[top[x]],tuop[x]);
166         x=father[top[x]];
167     
168     if(deep[x]<deep[to])
169     
170         swap(x,to);
171     
172     ans+=cha(1,1,n,tuop[to],tuop[x]);
173     return ans;
174 
175 int qmax(int x,int to)
176 
177     int ans=-inf;
178     while(top[x]!=top[to])
179     
180         if(deep[top[x]]<deep[top[to]])
181         
182             swap(x,to);
183         
184         
185         ans=max(ans,chamax(1,1,n,tuop[top[x]],tuop[x]));
186         x=father[top[x]];
187     
188     if(deep[x]<deep[to])
189     
190         swap(x,to);
191     
192     ans=max(ans,chamax(1,1,n,tuop[to],tuop[x]));
193     return ans;
194 
195 int main()
196 
197     //freopen("www.out","w",stdout);
198     memset(a,0,sizeof(a));
199     memset(head,0,sizeof(head));
200     scanf("%d",&n);
201     for(int i=1;i<n;i++)
202     
203         int u;
204         int v;
205         scanf("%d%d",&u,&v);
206         add(u,v);
207         add(v,u);
208     
209     for(int i=1;i<=n;i++)
210     
211         scanf("%d",&a[i]);
212     
213     deep[1]=1;
214     father[1]=1;
215     dfs1(1,-1);
216     dfs2(1,1);
217     build(1,1,n);
218     int T;
219     scanf("%d",&T);
220     while(T--)
221     
222         char flag[10];
223         int x;
224         int y;
225         scanf("%s%d%d",flag,&x,&y);
226         if(flag[1]==H)
227         
228             jia(1,1,n,tuop[x],y);
229         
230         else
231         if(flag[1]==M)
232         
233             printf("%d\n",qmax(x,y));
234         
235         else
236         if(flag[1]==S)
237         
238             printf("%d\n",qsum(x,y));
239         
240     
241     return 0;
242 

 

 

以上是关于P2590 [ZJOI2008]树的统计的主要内容,如果未能解决你的问题,请参考以下文章

P2590 [ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计(LCT)

P2590 [ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计