zoukankan      html  css  js  c++  java
  • [BZOJ4034] [HAOI2015] T2 (树链剖分)

    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 。

    Source

      鸣谢bhiaibogf提供

    Solution

      树链剖分,用线段树维护点权;对子树的修改就是区间修改,因为其dfs序是连续的

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 struct edge
      4 {
      5     int v, nxt;
      6 }e[200005];
      7 struct point
      8 {
      9     int val, siz, fa, son, dfn, top;
     10 }p[100005];
     11 struct seg
     12 {
     13     long long val, lazy;
     14 }a[300005];
     15 int fst[100005], ptot;
     16 
     17 void addedge(int i, int u, int v)
     18 {
     19     e[i] = (edge){v, fst[u]}, fst[u] = i;
     20 }
     21 
     22 void DFS1(int u)
     23 {
     24     p[u].siz = 1;
     25     for(int i = fst[u]; i; i = e[i].nxt)
     26         if(p[u].fa != e[i].v)
     27         {
     28             p[e[i].v].fa = u;
     29             DFS1(e[i].v);
     30             p[u].siz += p[e[i].v].siz;
     31             if(p[e[i].v].siz > p[p[u].son].siz)
     32                 p[u].son = e[i].v;
     33         }
     34 }
     35 
     36 void DFS2(int u, int top)
     37 {
     38     p[u].dfn = ++ptot, p[u].top = top;
     39     if(p[u].son) DFS2(p[u].son, top);
     40     for(int i = fst[u]; i; i = e[i].nxt)
     41         if(e[i].v != p[u].fa && e[i].v != p[u].son)
     42             DFS2(e[i].v, e[i].v);
     43 }
     44 
     45 void push_up(int o, int l, int r)
     46 {
     47     a[o].val = a[o << 1].val + a[o << 1 | 1].val;
     48     a[o].val += a[o].lazy * (r - l + 1);
     49 }
     50 
     51 void push_down(int o, int l, int r)
     52 {
     53     int mid = (l + r) >> 1;
     54     if(l == r) return;
     55     if(a[o].lazy)
     56     {
     57         a[o << 1].lazy += a[o].lazy;
     58         a[o << 1].val += a[o].lazy * (mid - l + 1);
     59         a[o << 1 | 1].lazy += a[o].lazy;
     60         a[o << 1 | 1].val += a[o].lazy * (r - mid);
     61         a[o].lazy = 0;
     62     }
     63 }
     64 
     65 void update(int o, int l, int r, int ql, int qr, int val)
     66 {
     67     int mid = (l + r) >> 1;
     68     push_down(o, l, r);
     69     if(ql <= l && r <= qr)
     70     {
     71         a[o].lazy += val;
     72         a[o].val += (long long)val * (r - l + 1);
     73         return;
     74     }
     75     if(ql <= mid) update(o << 1, l, mid, ql, qr, val);
     76     if(mid < qr) update(o << 1 | 1, mid + 1, r, ql, qr, val);
     77     push_up(o, l, r);
     78 }
     79 
     80 long long query(int o, int l, int r, int ql, int qr)
     81 {
     82     int mid = (l + r) >> 1;
     83     long long ans = 0;
     84     push_down(o, l, r);
     85     if(ql <= l && r <= qr) return a[o].val;
     86     if(ql <= mid) ans = query(o << 1, l, mid, ql, qr);
     87     if(mid < qr) ans += query(o << 1 | 1, mid + 1, r, ql, qr);
     88     return ans;
     89 }
     90 
     91 int main()
     92 {
     93     int n, m, u, v, op, x, val;
     94     long long ans;
     95     scanf("%d%d", &n, &m);
     96     for(int i = 1; i <= n; ++i)
     97         scanf("%d", &p[i].val);
     98     for(int i = 1; i < n; ++i)
     99     {
    100         scanf("%d%d", &u, &v);
    101         addedge(i << 1, u, v);
    102         addedge(i << 1 | 1, v, u);
    103     }
    104     DFS1(1), DFS2(1, 1);
    105     for(int i = 1; i <= n; ++i)
    106         update(1, 1, n, p[i].dfn, p[i].dfn, p[i].val);
    107     while(m--)
    108     {
    109         scanf("%d", &op);
    110         if(op == 1)
    111         {
    112             scanf("%d%d", &x, &val);
    113             update(1, 1, n, p[x].dfn, p[x].dfn, val);
    114         }
    115         else if(op == 2)
    116         {
    117             scanf("%d%d", &x, &val);
    118             update(1, 1, n, p[x].dfn, p[x].dfn + p[x].siz - 1, val);
    119         }
    120         else
    121         {
    122             scanf("%d", &x);
    123             ans = 0;
    124             while(x)
    125             {
    126                 ans += query(1, 1, n, p[p[x].top].dfn, p[x].dfn);
    127                 x = p[p[x].top].fa;
    128             }
    129             printf("%lld
    ", ans);
    130         }
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    最近相对闲点,写个笔记2
    最近相对闲点,写个笔记
    ORACLE 调优
    静态工厂方法与构造函数 创建类 区别
    组合与继承 区别
    Java异常
    abstract class 和 interface 区别
    java中的io系统详解
    Tomcat Apache 区别
    Vmware 下的网络模式配置
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5619362.html
Copyright © 2011-2022 走看看