zoukankan      html  css  js  c++  java
  • 【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
    ", 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
    ", QMAX(l, r));
    192                }else{
    193                   int l, r;
    194                   scanf("%d%d", &l, &r);
    195                   printf("%d
    ", 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
  • 相关阅读:
    寻找完全数(C++)
    莱布尼兹三角形(C++)
    简单的素数问题(C++)
    ubuntu17.04下安装LNMP
    ubuntu下连接mysql出现Access denied for user 'rose'@'localhost' (using password: NO)的解决方法
    快速理解面向对象的PHP编程--基础篇
    百度电面总结
    操作系统基础知识
    快速理解C语言指针
    新手学习MongoDB的基本命令
  • 原文地址:https://www.cnblogs.com/hoskey/p/4341386.html
Copyright © 2011-2022 走看看