zoukankan      html  css  js  c++  java
  • bzoj 4034[HAOI2015]树上操作

    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    Input

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 
    行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
    第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    Output

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    Sample Input

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    Sample Output

    6
    9
    13

    HINT

     对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

    一道树链剖分的练手题,以为一颗子树的DFS序是连续的,所以对子树的修改就相当于对一段区间的修改。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define LL long long
      6 
      7 using namespace std;
      8 
      9 int N, M;
     10 LL ans = 0;
     11 const int MAXN = 2e5 + 10;
     12 int size[MAXN], son[MAXN], top[MAXN], fa[MAXN], dfn[MAXN], out[MAXN];
     13 LL val[MAXN];
     14 int m[MAXN];
     15 int head[MAXN], deep[MAXN];
     16 
     17 int cnt = 0;
     18 struct segment {
     19     LL val;
     20     LL len;
     21     LL lazy;
     22 } seg[MAXN * 10];
     23 
     24 struct edge {
     25     int v, next;
     26 } g[MAXN * 2];
     27 
     28 inline LL read()
     29 {
     30     LL x = 0, w = 1; char ch = 0;
     31     while(ch < '0' || ch > '9') {
     32         if(ch == '-') {
     33             w = -1;
     34         }
     35         ch = getchar();
     36     }
     37     while(ch >= '0' && ch <= '9') {
     38         x = x * 10 + ch - '0';
     39         ch = getchar();
     40     }
     41     return x * w;
     42 }
     43 
     44 void pushdown(int root)
     45 {
     46     seg[root * 2].lazy += seg[root].lazy;
     47     seg[root * 2 + 1].lazy += seg[root].lazy;
     48     seg[root * 2].val += seg[root * 2].len * seg[root].lazy;
     49     seg[root * 2 + 1].val += seg[root * 2 + 1].len * seg[root].lazy;
     50     seg[root].lazy = 0;
     51 }
     52 
     53 void pushup(int root)
     54 {
     55     seg[root].val = seg[root * 2].val + seg[root * 2 + 1].val;
     56 }
     57 
     58 void build(int l, int r, int root)
     59 {
     60     seg[root].len = r - l + 1;
     61     if(l == r) {
     62         seg[root].val = val[m[l]];
     63         return;
     64     }
     65     int mid = (l + r) >> 1;
     66     build(l, mid, root * 2);
     67     build(mid + 1, r, root * 2 + 1);
     68     pushup(root);
     69 }
     70 
     71 void dfs1(int x)
     72 {
     73     deep[x] = deep[fa[x]] + 1;
     74     size[x] = 1;
     75     for(int j = head[x]; j; j = g[j].next) {
     76         int to = g[j].v;
     77         if(fa[x] != to) {
     78             fa[to] = x;
     79             dfs1(to);
     80             size[x] += size[to];
     81             if(size[son[x]] < size[to]) {
     82                 son[x] = to;
     83             }
     84         }
     85     }
     86 }
     87 
     88 void dfs2(int x, int tp)
     89 {
     90     top[x] = tp;
     91     dfn[x] = ++cnt;
     92     m[cnt] = x;
     93     if(son[x]) {
     94         dfs2(son[x], tp);
     95     }
     96     for(int j = head[x]; j; j = g[j].next) {
     97         int to = g[j].v;
     98         if(!dfn[to]) {
     99             dfs2(to, to);
    100         }
    101     }
    102     out[x] = cnt;
    103 }
    104 
    105 void update(int ul, int ur, int l, int r, int root, LL k)
    106 {
    107     if(ul <= l && ur >= r) {
    108         seg[root].val += seg[root].len * k;
    109         seg[root].lazy += k;
    110         return;
    111     }
    112     int mid = (l + r) >> 1;
    113     pushdown(root);
    114     if(mid >= ul) {
    115         update(ul, ur, l, mid, root * 2, k);
    116     }
    117     if(ur > mid) {
    118         update(ul, ur, mid + 1, r, root * 2 + 1, k);
    119     }
    120     pushup(root);
    121 }
    122 
    123 LL query(int ql, int qr, int l, int r, int root)
    124 {
    125     if(ql <= l && qr >= r) {
    126         return seg[root].val;
    127     }
    128     pushdown(root);
    129     LL sum = 0;
    130     int mid = (l + r) >> 1;
    131     if(mid >= ql) {
    132         sum += query(ql, qr, l, mid, root * 2);
    133     }
    134     if(mid < qr) {
    135         sum += query(ql, qr, mid + 1, r, root * 2 + 1);
    136     }
    137     return sum;
    138 }
    139 
    140 void addedge(int u, int v)
    141 {
    142     g[++cnt].v = v;
    143     g[cnt].next = head[u];
    144     head[u] = cnt;
    145 }
    146 
    147 LL cal(int x)
    148 {
    149     LL sum = 0;
    150     while(top[x] != 1) {
    151         sum += query(dfn[top[x]], dfn[x], 1, N, 1);
    152         x = fa[top[x]];
    153     }
    154     sum += query(1, dfn[x], 1, N, 1);
    155     return sum;
    156 }
    157 
    158 int main()
    159 {
    160     N = read(), M = read();
    161     for(int i = 1; i <= N; i++) {
    162         val[i] = read();
    163     }
    164     for(int i = 1; i < N; i++) {
    165         int u = read(), v = read();
    166         addedge(u, v);
    167         addedge(v, u);
    168     }
    169     cnt = 0;
    170     dfs1(1);
    171     dfs2(1, 1);
    172     build(1, N, 1);
    173 /*    for(int i = 1; i <= N; i++) {
    174         cout<<dfn[i]<<" "<<out[i]<<endl;
    175     }*/
    176     for(int i = 1; i <= M; i++) {
    177         int opr = read();
    178         if(opr == 1) {
    179             LL x = read(), a = read();
    180             update(dfn[x], dfn[x], 1, N, 1, a);
    181         } else if(opr == 2) {
    182             LL x = read(), a = read();
    183             update(dfn[x], out[x], 1, N, 1, a);
    184         } else {
    185             int x = read();
    186             ans = cal(x);
    187             printf("%lld
    ", ans);
    188         }
    189     }
    190     return 0;
    191 }
    View Code
  • 相关阅读:
    Java并发编程原理与实战二十九:Exchanger
    Java并发编程原理与实战二十八:信号量Semaphore
    Java并发编程原理与实战二十七:循环栅栏:CyclicBarrier
    Java并发编程原理与实战二十六:闭锁 CountDownLatch
    Java并发编程原理与实战二十五:ThreadLocal线程局部变量的使用和原理
    Java并发编程原理与实战二十四:简易数据库连接池
    Java并发编程原理与实战二十三:Condition原理分析
    Java并发编程原理与实战二十二:Condition的使用
    Java并发编程原理与实战二十一:线程通信wait&notify&join
    Java并发编程原理与实战二十:线程安全性问题简单总结
  • 原文地址:https://www.cnblogs.com/wuenze/p/8666690.html
Copyright © 2011-2022 走看看