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 }