zoukankan      html  css  js  c++  java
  • [luoguP3178] [HAOI2015]树上操作(dfs序 + 线段树 || 树链剖分)

    传送门

    树链剖分固然可以搞。

    但还有另一种做法,可以看出,增加一个节点的权值会对以它为根的整棵子树都有影响,相当于给整棵子树增加一个值。

    而给以某一节点 x 为根的子树增加一个权值也会影响当前子树,节点 y 所增加的值为 dis[y] * z - (dis[x] - 1) * z,每个节点都会增加 -(dis[x] - 1) * z ,

    询问时只用加上 dis[y] * y 和当前节点 y 的权值。

    给整棵子树增加一个权值可以用 dfs 序 + 线段树搞, dis 数组可以预处理出来。

    ——代码

      1 #include <cstdio>
      2 #include <cstring>
      3 #define LL long long
      4 #define root 1, 1, n
      5 #define ls now << 1, l, mid
      6 #define rs now << 1 | 1, mid + 1, r
      7 
      8 using namespace std;
      9 
     10 const int MAXN = 100001;
     11 int n, m, cnt, tot;
     12 int head[MAXN], next[MAXN << 1], to[MAXN << 1], tid[MAXN], size[MAXN];
     13 LL a[MAXN << 2], b[MAXN << 2], val[MAXN], dis[MAXN];
     14 
     15 inline void add(int x, int y)
     16 {
     17     to[cnt] = y;
     18     next[cnt] = head[x];
     19     head[x] = cnt++;
     20 } 
     21 
     22 inline void dfs(int u)
     23 {
     24     int i, v; 
     25     tid[u] = ++tot;
     26     size[u] = 1;
     27     for(i = head[u]; i != -1; i = next[i])
     28     {
     29         v = to[i];
     30         if(!size[v])
     31         {
     32             dis[v] = dis[u] + 1;
     33             dfs(v);
     34             size[u] += size[v];
     35         }
     36     }
     37 }
     38 
     39 inline void push_down(int now)
     40 {
     41     a[now << 1] += a[now];
     42     a[now << 1 | 1] += a[now];
     43     b[now << 1] += b[now];
     44     b[now << 1 | 1] += b[now];
     45     a[now] = b[now] = 0;
     46 }
     47 
     48 inline void update(LL x, LL y, int ql, int qr, int now, int l, int r)
     49 {
     50     if(ql <= l && r <= qr)
     51     {
     52         a[now] += x;
     53         b[now] += y;
     54         return;
     55     }
     56     push_down(now);
     57     int mid = (l + r) >> 1;
     58     if(ql <= mid) update(x, y, ql, qr, ls);
     59     if(mid < qr) update(x, y, ql, qr, rs);
     60 }
     61 
     62 inline LL query(int u, int x, int now, int l, int r)
     63 {
     64     if(l == r) return dis[u] * a[now] + b[now];
     65     push_down(now);
     66     int mid = (l + r) >> 1;
     67     if(x <= mid) return query(u, x, ls);
     68     else return query(u, x, rs);
     69 }
     70 
     71 int main()
     72 {
     73     int i, x, z;
     74     LL y;
     75     scanf("%d %d", &n, &m);
     76     for(i = 1; i <= n; i++)    scanf("%lld", &val[i]);
     77     memset(head, -1, sizeof(head));
     78     for(i = 1; i < n; i++)
     79     {
     80         scanf("%d %d", &x, &y);
     81         add(x, y);
     82         add(y, x);
     83     }
     84     dis[1] = 1;
     85     dfs(1);
     86     for(i = 1; i <= n; i++) update(0, val[i], tid[i], tid[i] + size[i] - 1, root);
     87     for(i = 1; i <= m; i++)
     88     {
     89         scanf("%d %d", &z, &x);
     90         if(z == 1)
     91         {
     92             scanf("%lld", &y);
     93             update(0, y, tid[x], tid[x] + size[x] - 1, root);
     94         }
     95         else if(z == 2)
     96         {
     97             scanf("%lld", &y);
     98             update(y, -((dis[x] - 1) * y), tid[x], tid[x] + size[x] - 1, root);
     99         }
    100         else printf("%lld
    ", query(x, tid[x], root));
    101     }
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6811145.html
Copyright © 2011-2022 走看看