[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 const int N=30005;
  7 struct Node
  8 {
  9   int next,to;
 10 }edge[2*N];
 11 int cm[4*N],cs[4*N];
 12 int size[N],top[N],num,head[N],son[N],dfn[N],id[N],cnt,fa[N];
 13 int dep[N],w[N],n,q;
 14 char s[21];
 15 void add(int u,int v)
 16 {
 17   num++;
 18   edge[num].next=head[u];
 19   head[u]=num;
 20   edge[num].to=v;
 21 }
 22 void dfs1(int x,int pa)
 23 {int i;
 24   size[x]=1;
 25   for (i=head[x];i;i=edge[i].next)
 26     {
 27       int v=edge[i].to;
 28       if (v==pa) continue;
 29       dfs1(v,x);
 30       size[x]+=size[v];
 31       if (size[v]>size[son[x]]) son[x]=v;
 32     }
 33 }
 34 void dfs2(int x,int pa,int tp)
 35 {int i;
 36   dfn[x]=++cnt;
 37   id[cnt]=x;fa[x]=pa;
 38   top[x]=tp;dep[x]=dep[pa]+1;
 39   if (son[x])
 40     dfs2(son[x],x,tp);
 41   for (i=head[x];i;i=edge[i].next)
 42     {
 43       int v=edge[i].to;
 44       if (v==pa||v==son[x]) continue;
 45       dfs2(v,x,v);
 46     }
 47 }
 48 void pushup(int rt)
 49 {
 50   cm[rt]=max(cm[rt<<1],cm[rt<<1|1]);
 51   cs[rt]=cs[rt<<1]+cs[rt<<1|1];
 52 }
 53 void build(int rt,int l,int r)
 54 {
 55   if (l==r)
 56     {
 57       cm[rt]=w[id[l]];
 58       cs[rt]=w[id[l]];
 59       return;
 60     }
 61   int mid=(l+r)>>1;
 62   build(rt<<1,l,mid);
 63   build(rt<<1|1,mid+1,r);
 64   pushup(rt);
 65 }
 66 void update(int rt,int l,int r,int x,int k)
 67 {
 68   if (l==r)
 69     {
 70       cm[rt]=cs[rt]=k;
 71       return;
 72     }
 73   int mid=(l+r)>>1;
 74   if (x<=mid) update(rt<<1,l,mid,x,k);
 75   else update(rt<<1|1,mid+1,r,x,k);
 76   pushup(rt);
 77 }
 78 int query_max(int rt,int l,int r,int L,int R)
 79 {
 80   if (l>=L&&r<=R)
 81     {
 82       return cm[rt];
 83     }
 84   int mid=(l+r)>>1,s=-2e9;
 85   if (L<=mid) s=max(s,query_max(rt<<1,l,mid,L,R));
 86   if (R>mid) s=max(s,query_max(rt<<1|1,mid+1,r,L,R));
 87   pushup(rt);
 88   return s;
 89 }
 90 int query_sum(int rt,int l,int r,int L,int R)
 91 {
 92   if (l>=L&&r<=R)
 93     {
 94       return cs[rt];
 95     }
 96   int mid=(l+r)>>1,s=0;
 97   if (L<=mid) s=s+query_sum(rt<<1,l,mid,L,R);
 98   if (R>mid) s=s+query_sum(rt<<1|1,mid+1,r,L,R);
 99   pushup(rt);
100   return s;
101 }
102 int get_max(int x,int y)
103 {
104   int as=-2e9;
105   while (top[x]!=top[y])
106     {
107       if (dep[top[x]]<dep[top[y]]) swap(x,y);
108       as=max(as,query_max(1,1,n,dfn[top[x]],dfn[x]));
109       x=fa[top[x]];
110     }
111   if (dfn[x]>dfn[y]) swap(x,y);
112   as=max(as,query_max(1,1,n,dfn[x],dfn[y]));
113   return as;
114 }
115 int get_sum(int x,int y)
116 {
117   int as=0;
118   while (top[x]!=top[y])
119     {
120       if (dep[top[x]]<dep[top[y]]) swap(x,y);
121       as=as+query_sum(1,1,n,dfn[top[x]],dfn[x]);
122       x=fa[top[x]];
123     }
124   if (dfn[x]>dfn[y]) swap(x,y);
125   as=as+query_sum(1,1,n,dfn[x],dfn[y]);
126   return as;
127 }
128 int main()
129 {int i,u,v,x,y;
130   cin>>n;
131   for (i=1;i<=n-1;i++)
132     {
133       scanf("%d%d",&u,&v);
134       add(u,v);add(v,u);
135     }
136   for (i=1;i<=n;i++)
137       scanf("%d",&w[i]);
138   dfs1(1,0);dfs2(1,0,1);
139   build(1,1,n);
140   cin>>q;
141   while (q--)
142     {
143       scanf("%s",s);
144       if (s[0]=='C')
145     {
146       scanf("%d%d",&x,&y);
147       w[x]=y;
148       update(1,1,n,dfn[x],y);
149     }
150       else if (s[1]=='M')
151     {
152       scanf("%d%d",&x,&y);
153       printf("%d\n",get_max(x,y));
154     }
155       else
156     {
157       scanf("%d%d",&x,&y);
158       printf("%d\n",get_sum(x,y));
159     }
160     }
161 }

 

posted @ 2018-03-01 15:44  Z-Y-Y-S  阅读(283)  评论(0编辑  收藏  举报