[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之间。

 

分析:

一道比树剖模板题还简单的。。。模板题???emmmm。。。

 

CODE:

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 const int N=30005;
  8 const int M=100005;
  9 int n,m,summ,maxx;
 10 int seg[M],rev[M],size[M],son[M],top[M],dep[M];
 11 int sum[M],num[M],father[M],Max[M];
 12 int head[M],next[M],to[M],tot;
 13 inline int read(){
 14     int res=0;
 15     int f=1;
 16     char c=getchar();
 17     while (c>'9'||c<'0') {
 18         if (c=='-') f=-1;
 19         c=getchar();
 20     }
 21     while (c<='9'&&c>='0') {
 22         res=(res<<3)+(res<<1)+c-'0';
 23         c=getchar();
 24     }
 25     return res*f;
 26 }
 27 void add(int u,int v){
 28     next[++tot]=head[u];
 29     head[u]=tot;
 30     to[tot]=v;
 31     return ;
 32 }
 33 inline void insert(int u,int v){
 34     add(u,v);
 35     add(v,u);
 36     return ;
 37 }
 38 void query(int k,int l,int r,int L,int R){
 39     if (L>r||R<l) return ;
 40     if (L<=l&&r<=R) {
 41         summ+=sum[k];
 42         maxx=max(maxx,Max[k]);
 43         return ;
 44     }
 45     int m=l+r>>1;
 46     if (m>=L) query(k<<1,l,m,L,R);
 47     if (m<R) query(k<<1|1,m+1,r,L,R);
 48 }
 49 void change(int k,int l,int r,int val,int pos){
 50     if (pos>r||pos<l) return ;
 51     if (l==r&&r==pos){
 52         sum[k]=val;
 53         Max[k]=val;
 54         return ;
 55     }
 56     int m=l+r>>1;
 57     if (m>=pos) change(k<<1,l,m,val,pos);
 58     if (m<pos) change(k<<1|1,m+1,r,val,pos);
 59     sum[k]=sum[k<<1]+sum[k<<1|1];
 60     Max[k]=max(Max[k<<1],Max[k<<1|1]);
 61 }
 62 void build(int k,int l,int r){
 63     int m=l+r>>1;
 64     if (l==r){Max[k]=sum[k]=num[rev[l]];return;}
 65     build(k<<1,l,m);
 66     build(k<<1|1,m+1,r);
 67     sum[k]=sum[k<<1]+sum[k<<1|1];
 68     Max[k]=max(Max[k<<1],Max[k<<1|1]);
 69     return;
 70 }
 71 void dfs1(int u,int fa){
 72     dep[u]=dep[fa]+1;
 73     father[u]=fa;
 74     size[u]=1;
 75     for (int i=head[u];i;i=next[i]){
 76         int v=to[i];
 77         if (v!=fa){
 78             dfs1(v,u);
 79             size[u]+=size[v];
 80             if (size[v]>size[son[u]]) son[u]=v;
 81         }
 82     }
 83     return;
 84 }
 85 void dfs2(int u,int fa){
 86     if (son[u]){
 87         seg[son[u]]=++seg[0];
 88         top[son[u]]=top[u];
 89         rev[seg[0]]=son[u];
 90         dfs2(son[u],u);
 91     }
 92     for (int i=head[u];i;i=next[i]){
 93         int v=to[i];
 94         if (!top[v]) {
 95             seg[v]=++seg[0];
 96             rev[seg[0]]=v;
 97             top[v]=v;
 98             dfs2(v,u);
 99         }
100     }
101     return;
102 }
103 void ask(int x,int y){
104     int fx=top[x],fy=top[y];
105     while (fx!=fy){
106         if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
107         query(1,1,seg[0],seg[fx],seg[x]);
108         x=father[fx];fx=top[x];
109     }
110     if (dep[x]>dep[y]) swap(x,y);
111     query(1,1,seg[0],seg[x],seg[y]);
112 }
113 int main() {
114     n=read();
115     for (int i=1;i<n;i++) insert(read(),read());
116     for (int i=1;i<=n;i++) num[i]=read();
117     dfs1(1,0);
118     seg[0]=seg[1]=top[1]=rev[1]=1;
119     dfs2(1,0);
120     build(1,1,seg[0]);
121     m=read();
122     while (m--){
123         char s[15];
124         int u,v;
125         cin>>s+1;
126         u=read(),v=read();
127         if (s[1]=='C') change(1,1,seg[0],v,seg[u]);
128         else{
129             summ=0;
130             maxx=-1<<30;
131             ask(u,v);
132             if (s[2]=='M') cout<<maxx<<endl;
133             else cout<<summ<<endl;
134         }
135     }
136     //system("pause");
137     return 0;
138 }

 

posted @ 2019-07-25 12:41  Sword_Art_Online  阅读(170)  评论(0编辑  收藏  举报