BZOJ1036 [ZJOI2008] 树的统计Count

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”的操作,每行输出一个整数表示要求输出的结果。 

经典的树链剖分,用线段树维护即可。

只是发现以前写的时候没有开博客,补一下题解。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 #include <climits>
  7 #define rep(i,l,r) for(int i=l; i<=r; i++)
  8 #define clr(x,y) memset(x,y,sizeof(x))
  9 #define travel(x) for(int i=last[x]; i; i=edge[i].pre)
 10 typedef long long ll;
 11 using namespace std;
 12 const int INF = 0x7fffffff;
 13 const int maxn = 30010;
 14 struct Edge{
 15     int pre,to;
 16 }edge[maxn<<1];
 17 struct segnode{
 18     int l,r,mx,sum;
 19 }tree[maxn<<2];
 20 int n,m,x,y,segnum=0,tot=0,depth[maxn],last[maxn],v[maxn],size[maxn],pos[maxn],belong[maxn],fa[maxn];
 21 char c[6];
 22 bool vis[maxn];
 23 inline int read(){
 24     int ans = 0, f = 1;
 25     char c = getchar();
 26     while (!isdigit(c)){
 27         if (c == '-') f = -1;
 28         c = getchar();
 29     }
 30     while (isdigit(c)){
 31         ans = ans * 10 + c - '0';
 32         c = getchar();
 33     }
 34     return ans * f;
 35 }
 36 inline void addedge(int x,int y){
 37     edge[++tot].pre = last[x];
 38     edge[tot].to = y;
 39     last[x] = tot;
 40 }
 41 void dfs(int x){
 42     vis[x] = 1; size[x] = 1;
 43     travel(x){
 44         if (!vis[edge[i].to]){
 45             depth[edge[i].to] = depth[x] + 1;
 46             fa[edge[i].to] = x;
 47             dfs(edge[i].to);
 48             size[x] += size[edge[i].to];
 49         }
 50     }
 51 }
 52 void dfs2(int x,int chain){
 53     int k = 0; pos[x] = ++segnum;
 54     belong[x] = chain;
 55     travel(x){
 56         if (depth[edge[i].to] > depth[x] && size[edge[i].to] > size[k])
 57         k = edge[i].to;
 58     }
 59     if (!k) return;
 60     dfs2(k,chain);
 61     travel(x){
 62         if (depth[edge[i].to] > depth[x] && k != edge[i].to)
 63         dfs2(edge[i].to,edge[i].to);
 64     }
 65 }
 66 void build(int u,int v,int w){
 67     tree[w].l = u;
 68     tree[w].r = v;
 69     if (u == v) return;
 70     build(u,(u+v)>>1,w<<1);
 71     build(((u+v)>>1)+1,v,w<<1|1);
 72 }
 73 int querysum(int u,int v,int w){
 74     if (u == tree[w].l && v == tree[w].r) return tree[w].sum;
 75     if (v <= tree[w<<1].r) return querysum(u,v,w<<1);
 76     if (u > tree[w<<1].r) return querysum(u,v,w<<1|1);
 77     return querysum(u,tree[w<<1].r,w<<1) + querysum(tree[w<<1|1].l,v,w<<1|1);
 78 }
 79 int querymx(int u,int v,int w){
 80     if (u == tree[w].l && v == tree[w].r) return tree[w].mx;
 81     if (v <= tree[w<<1].r) return querymx(u,v,w<<1);
 82     if (u > tree[w<<1].r) return querymx(u,v,w<<1|1);
 83     return max(querymx(u,tree[w<<1].r,w<<1), querymx(tree[w<<1|1].l,v,w<<1|1));
 84 }
 85 void update(int u,int w,int z){
 86     if (tree[w].l == tree[w].r){
 87         tree[w].sum = tree[w].mx = z;
 88         return;
 89     }
 90     int mid = (tree[w].l + tree[w].r) >> 1;
 91     if (u <= mid) update(u,w<<1,z);
 92     else update(u,w<<1|1,z);
 93     tree[w].sum = tree[w<<1].sum + tree[w<<1|1].sum;
 94     tree[w].mx = max(tree[w<<1].mx, tree[w<<1|1].mx);
 95 }
 96 int solvesum(int x,int y){
 97     int res = 0;
 98     while (belong[x] != belong[y]){
 99         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
100         res += querysum(pos[belong[x]],pos[x],1);
101         x = fa[belong[x]];
102     }
103     if (depth[x] < depth[y]) swap(x,y);
104     res += querysum(pos[y],pos[x],1);
105     return res;
106 }
107 int solvemx(int x,int y){
108     int res = 0 - INF;
109     while (belong[x] != belong[y]){
110         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
111         res = max(res,querymx(pos[belong[x]],pos[x],1));
112         x = fa[belong[x]];
113     }
114     if (depth[x] < depth[y]) swap(x,y);
115     res = max(res,querymx(pos[y],pos[x],1));
116     return res;
117 }
118 int main(){
119     n = read();
120     rep(i,1,n-1){
121         x = read(); y = read();
122         addedge(x,y); addedge(y,x);
123     }
124     rep(i,1,n) v[i] = read();
125     depth[1] = 0; dfs(1);
126     dfs2(1,1);
127     build(1,n,1);
128     rep(i,1,n) update(pos[i],1,v[i]);
129     m = read();
130     rep(i,1,m){
131         scanf("%s",c); x = read(); y = read();
132         if (c[1] == 'M'){
133             printf("%d\n",solvemx(x,y));
134         }
135         else if (c[1] == 'S'){
136             printf("%d\n",solvesum(x,y));
137         }
138         else{
139             v[x] = y;
140             update(pos[x],1,y);
141         }
142     }
143     return 0;
144 }
View Code

 

posted on 2016-05-24 13:55  ACMICPC  阅读(212)  评论(0编辑  收藏  举报

导航