zoukankan      html  css  js  c++  java
  • BZOJ4034 [HAOI2015]T2

    本来直接树剖就好了,但是树剖会多一个log非常不开心

    我们来考虑维护dfs序,那么序列上的每个元素表示该点的答案

    单点点权修改操作就是dfs序上段加操作

    子树修改操作就是dfs序上段减一个数,然后每个点加上固定值乘以它的深度

    具体的来讲。。。dfs序上每个点维护三个东西,叫v,tag和times,分别表示当前值,区间的加减,每个点的深度

    单点修改就是v += d,而子树修改就是tag += d

    于是用线段树维护就好了

      1 /**************************************************************
      2     Problem: 4034
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:1128 ms
      7     Memory:21796 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11  
     12 using namespace std;
     13 typedef long long ll;
     14 const int N = 1e5 + 5;
     15 const int Maxlen = N * 50;
     16  
     17 inline int read();
     18 inline void print(ll);
     19  
     20 struct edge {
     21     int next, to;
     22     edge(int _n = 0, int _t = 0) : next(_n), to(_t) {}
     23 } e[N << 1];
     24  
     25 int first[N], tot;
     26  
     27 struct seg {
     28     seg *ls, *rs;
     29     int times;
     30     ll v, tag;
     31      
     32     seg() {
     33         ls = rs = NULL;
     34         v = tag = times = 0;
     35     }
     36      
     37     #define Len (1 << 16)
     38     inline void* operator new(size_t) {
     39         static seg *mempool, *c;
     40         if (c == mempool)
     41             mempool = (c = new seg[Len]) + Len;
     42         *c = seg();
     43         return c++;
     44     }
     45     #undef Len
     46      
     47     inline void push() {
     48         if (v) {
     49             if (ls) ls -> v += v;
     50             if (rs) rs -> v += v;
     51             v = 0;
     52         }
     53         if (tag) {
     54             if (ls) ls -> tag += tag;
     55             if (rs) rs -> tag += tag;
     56             tag = 0;
     57         }
     58     }
     59      
     60     #define mid (l + r >> 1)
     61     void build(int l, int r, ll *a, int *b) {
     62         if (l == r) {
     63             v = a[l], times = b[l];
     64             return;
     65         }
     66         ls = new()seg, rs = new()seg;
     67         ls -> build(l, mid, a, b), rs -> build(mid + 1, r, a, b);
     68     }
     69      
     70     void modify(int l, int r, int L, int R, int d) {
     71         if (L <= l && r <= R) {
     72             v += d;
     73             return;
     74         }
     75         push();
     76         if (L <= mid) ls -> modify(l, mid, L, R, d);
     77         if (mid < R) rs -> modify(mid + 1, r, L, R, d);
     78     }
     79      
     80     void Modify(int l, int r, int L, int R, int dep, int d) {
     81         if (L <= l && r <= R) {
     82             v -= 1ll * d * (dep - 1), tag += d;
     83             return;
     84         }
     85         push();
     86         if (L <= mid) ls -> Modify(l, mid, L, R, dep, d);
     87         if (mid < R) rs -> Modify(mid + 1, r, L, R, dep, d);
     88     }
     89      
     90     ll query(int l, int r, int pos) {
     91         if (l == r) return v + tag * times;
     92         push();
     93         if (pos <= mid) return ls -> query(l, mid, pos);
     94         return rs -> query(mid + 1, r, pos);
     95     }
     96     #undef mid
     97 } *T;
     98  
     99 struct tree_node {
    100     int fa, v, dep;
    101     int st, ed;
    102 } tr[N];
    103  
    104 int n, m, cnt_seq;
    105 ll a[N];
    106 int b[N];
    107  
    108 char buf[Maxlen], *c = buf;
    109 int Len;
    110  
    111 inline void Add_Edges(int x, int y) {
    112     e[++tot] = edge(first[x], y), first[x] = tot;
    113     e[++tot] = edge(first[y], x), first[y] = tot;
    114 }
    115  
    116 #define y e[x].to
    117 void dfs(int p) {
    118     int x;
    119     a[tr[p].st = ++cnt_seq] = a[tr[tr[p].fa].st] + tr[p].v;
    120     b[cnt_seq] = tr[p].dep;
    121     for (x = first[p]; x; x = e[x].next)
    122         if (y != tr[p].fa) {
    123             tr[y].fa = p, tr[y].dep = tr[p].dep + 1;
    124             dfs(y);
    125         }
    126     tr[p].ed = cnt_seq;
    127 }
    128 #undef y
    129  
    130 int main() {
    131     Len = fread(c, 1, Maxlen, stdin);
    132     buf[Len] = '';
    133     int i, oper, x;
    134     n = read(), m = read();
    135     for (i = 1; i <= n; ++i) tr[i].v = read();
    136     for (i = 1; i < n; ++i)
    137         Add_Edges(read(), read());
    138     dfs(1);
    139     T = new()seg;
    140     T -> build(1, n, a, b);
    141     while (m--) {
    142         oper = read(), x = read();
    143         if (oper == 1) T -> modify(1, n, tr[x].st, tr[x].ed, read());
    144         if (oper == 2) T -> Modify(1, n, tr[x].st, tr[x].ed, tr[x].dep, read());
    145         if (oper == 3) print(T -> query(1, n, tr[x].st));
    146     }
    147     return 0;
    148 }
    149  
    150 inline int read() {
    151     static int x, sgn;
    152     x = 0, sgn = 1;
    153     while (*c < '0' || '9' < *c) {
    154         if (*c == '-') sgn = -1; 
    155         ++c;
    156     }
    157     while ('0' <= *c && *c <= '9')
    158         x = x * 10 + *c - '0', ++c;
    159     return sgn * x;
    160 }
    161  
    162 inline void print(ll t) {
    163     int tot = 0, pr[25];
    164     if (t < 0) putchar('-'), t = -t;
    165     tot = 0;
    166     while (t)
    167         pr[++tot] = t % 10, t /= 10;
    168     if (!tot) putchar('0');
    169     while (tot) putchar(pr[tot--] + '0');
    170     putchar('
    ');
    171 }
    View Code
  • 相关阅读:
    【URAL 1004】 floyd最小环
    【UVA 10881】 经典模拟题
    【HDU 1541】 树状数组(入门题)
    【HDU 4000】 树状数组
    【HDU 3391 && HDU 4431】 dfs+模拟
    【HDU 1058 & HDU 3199 类似丑数】 简单DP思想
    Acdream原创群赛3(部分题解)
    vfor实现双层循环嵌套
    vue获取当前时间并实时刷新时间
    vue+element ui实现左侧导航栏动态路由跳转
  • 原文地址:https://www.cnblogs.com/rausen/p/4477735.html
Copyright © 2011-2022 走看看