【BZOJ1036】【树链剖分】树的统计Count

Description

一 棵树上有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本身

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

Sample Input

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

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

Source

树的分治

【分析】

SB题,不说了。

  1 /*

  2 唐代李白

  3 《南陵别儿童入京》

  4 白酒新熟山中归,黄鸡啄黍秋正肥。

  5 呼童烹鸡酌白酒,儿女嬉笑牵人衣。

  6 高歌取醉欲自慰,起舞落日争光辉。

  7 游说万乘苦不早,著鞭跨马涉远道。

  8 会稽愚妇轻买臣,余亦辞家西入秦。

  9 仰天大笑出门去,我辈岂是蓬蒿人。

 10 */

 11 #include <iostream>

 12 #include <cstdio>

 13 #include <algorithm>

 14 #include <cstring>

 15 #include <vector>

 16 #include <utility>

 17 #include <iomanip>

 18 #include <string>

 19 #include <cmath>

 20 #include <queue>

 21 #include <assert.h>

 22 #include <map>

 23 #include <ctime>

 24 #include <cstdlib>

 25 #include <stack>

 26 #define LOCAL

 27 const int INF = 0x3f3f3f3f;

 28 const int MAXN = 100000  + 10;

 29 const int maxnode = 1000000;

 30 const int maxm= 30000 * 2 + 10;

 31 using namespace std;

 32 struct Node{

 33        int l, r;

 34        int Max, sum;

 35        Node *ch[2];

 36 }*root, mem[maxnode];

 37 struct Edge{

 38        int u, v;

 39 }edge[MAXN];

 40 

 41 int n, top[MAXN], fa[MAXN];

 42 int dep[MAXN], size[MAXN], son[MAXN];

 43 int head[MAXN], next[MAXN], to[MAXN];

 44 int pos[MAXN], Time, M, tot;

 45 

 46 void dfs_1(int u){

 47      size[u] = 1;

 48      son[u] = 0;

 49      for (int i = head[u]; i != -1; i = next[i]){

 50          int v = to[i];

 51          if (v == fa[u]) continue;

 52          fa[v] = u;

 53          dep[v] = dep[u] + 1;

 54          dfs_1(v);

 55          size[u] += size[v];

 56          if (size[v] > size[son[u]]) son[u] = v;

 57      }

 58 }

 59 //标号 

 60 void dfs_2(int u, int top_node){

 61      top[u] = top_node;

 62      pos[u] = ++Time;//这里就不是代表边了,而是点

 63      if (son[u]) dfs_2(son[u], top_node);

 64      

 65      for (int i = head[u]; i != -1; i = next[i]){

 66          int v = to[i];

 67          if (v == fa[u] || v == son[u]) continue;

 68          dfs_2(v, v);

 69      } 

 70 }

 71 void addEdge(int u, int v){

 72      to[M] = v;

 73      next[M] = head[u];

 74      head[u] = M++;

 75 }

 76 Node *NEW(int l, int r){

 77      Node *p = &mem[tot++];

 78      p->l = l;

 79      p->r = r;

 80      p->Max = p->sum = 0;

 81      return p;

 82 }

 83 //连区间修改都没有 

 84 void update(Node *&t){

 85      if (t->l == t->r) return;

 86      t->Max = max(t->ch[0]->Max, t->ch[1]->Max);

 87      t->sum = t->ch[1]->sum + t->ch[0]->sum; 

 88 }

 89 void build(Node *&t, int l, int r){

 90      if (t == NULL){

 91         t = NEW(l, r);

 92      }

 93      if (l == r) return;

 94      int mid = (l + r) >> 1;

 95      build(t->ch[0], l, mid);

 96      build(t->ch[1], mid + 1, r);  

 97 }

 98 void change(Node *&t, int l, int x){

 99      if (t->l == l && t->r == l){

100         t->sum = t->Max = x;

101         return;

102      }

103      int mid = (t->l + t->r) >> 1;

104      if (l <= mid) change(t->ch[0], l, x);

105      else change(t->ch[1], l, x);

106      

107      update(t); 

108 }

109 void init(){

110      memset(dep, 0, sizeof(dep));

111      memset(head, -1, sizeof(head));

112      

113      M = Time = tot = 0;

114      scanf("%d", &n);

115      for (int i = 1; i < n; i++){

116          scanf("%d%d", &edge[i].u, &edge[i].v);

117          addEdge(edge[i].u, edge[i].v);

118          addEdge(edge[i].v, edge[i].u);

119      }

120      fa[1] = 0;

121      size[0] = 0;

122      

123      dfs_1(1);

124      dfs_2(1, 1);

125      root = NULL;

126      build(root, 1, Time);

127      //因为不是边所以跟父亲没什么关系,不用对边进行更新 

128      for (int i = 1; i <= n; i++){

129          int t;

130          scanf("%d", &t);

131          change(root, pos[i], t);

132      }

133      //printf("%d\n", root->Max);

134 }

135 int query_sum(Node *&t, int l, int r){

136     if (l <= t->l && t->r <= r) return t->sum;

137     int mid = (t->l + t->r) >> 1;

138     int cnt = 0;

139     if (l <= mid) cnt += query_sum(t->ch[0], l, r);

140     if (r > mid) cnt += query_sum(t->ch[1], l, r);

141     return cnt;

142 }

143 int query_max(Node *&t, int l, int r){

144     if (l <= t->l && t->r <= r) return t->Max;

145     int mid = (t->l + t->r) >> 1;

146     int Ans = -INF;

147     if (l <= mid) Ans = max(Ans, query_max(t->ch[0], l, r));

148     if (r > mid) Ans = max(Ans, query_max(t->ch[1], l, r));

149     return Ans;

150 }

151 int QMAX(int l, int r){

152      int Ans = -INF;

153      while (top[l] != top[r]){

154            //低的往上爬 

155            if (dep[top[l]] < dep[top[r]]) swap(l, r);

156            Ans = max(Ans, query_max(root, pos[top[l]], pos[l]));

157            l = fa[top[l]];

158      }

159      //if (l == r) return Ans;

160      if (dep[l] > dep[r]) swap(l, r);

161      Ans = max(Ans, query_max(root, pos[l], pos[r]));

162      return Ans;

163 }

164 int QSUM(int l, int r){

165      int sum = 0;

166      while (top[l] != top[r]){

167            //低的往上爬 

168            if (dep[top[l]] < dep[top[r]]) swap(l, r);

169            sum += query_sum(root, pos[top[l]], pos[l]);

170            l = fa[top[l]];

171      }

172      //if (l == r) return sum;

173      if (dep[l] > dep[r]) swap(l, r);

174      sum += query_sum(root, pos[l], pos[r]);

175      return sum;

176 }

177 void work(){

178      int q;

179      scanf("%d", &q);

180      for (int i = 1; i <= q; i++){

181          char str[10];

182          scanf("%s", str);

183          if (str[0] == 'C'){

184             int l, x;

185             scanf("%d%d", &l, &x);

186             change(root, pos[l], x);

187          }else{

188                if (str[1] == 'M'){

189                   int l, r;

190                   scanf("%d%d", &l, &r);

191                   printf("%d\n", QMAX(l, r));

192                }else{

193                   int l, r;

194                   scanf("%d%d", &l, &r);

195                   printf("%d\n", QSUM(l, r));

196                }

197          }

198      }

199 }

200 

201 int main(){

202     int T;

203     

204     init();

205     work();

206     return 0;

207 }
View Code

 

你可能感兴趣的:(count)