• BZOJ2836 魔法树


    题意:树上进行两种操作:

    (1)链上+d

    (2)子树求和

    直接链剖即可,子树求和就dfs序即可。

    注意,dfs序按照重儿子在最先的序列,然后建立线段树。

      1 /**************************************************************
      2     Problem: 2836
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:4180 ms
      7     Memory:20264 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12  
     13 using namespace std;
     14 typedef long long ll;
     15  
     16 const int N = 100005;
     17  
     18 struct edge {
     19   int next, to;
     20   edge() {}
     21   edge(int _n, int _t) : next(_n), to(_t) {}
     22 } e[N];
     23  
     24 struct tree_node {
     25   int fa, son, sz, dep, st, ed, top;
     26 } tr[N];
     27  
     28 struct seg_node {
     29   seg_node *ls, *rs;
     30   int len;
     31   ll v, tag;
     32 } *root, mempool[N << 2], *cnt_seg = mempool, *null;
     33  
     34 int n, Q;
     35 int first[N], tot, cnt_q;
     36  
     37 int read() {
     38   int x = 0;
     39   char ch = getchar();
     40   while (ch < '0' || '9' < ch)
     41     ch = getchar();
     42   while ('0' <= ch && ch <= '9')
     43     (x *= 10) += ch - '0', ch = getchar();
     44   return x;
     45 }
     46  
     47 inline void add_edge(int x, int y) {
     48   e[++tot] = edge(first[x], y);
     49   first[x] = tot;
     50 }
     51  
     52 #define y e[x].to
     53 #define Son tr[p].son
     54 void dfs(int p) {
     55   int x;
     56   tr[p].sz = 1;
     57   for (x = first[p]; x; x = e[x].next) {
     58     tr[y].dep = tr[p].dep + 1;
     59     dfs(y);
     60     tr[p].sz += tr[y].sz;
     61     if (Son == 0 || tr[y].sz > tr[Son].sz)
     62       Son = y;
     63   }
     64 }
     65  
     66 void DFS(int p) {
     67   int x;
     68   tr[p].st = ++cnt_q;
     69   if (Son) {
     70     tr[Son].top = tr[p].top;
     71     DFS(Son);
     72   }
     73   for (x = first[p]; x; x = e[x].next)
     74     if (y != Son) {
     75       tr[y].top = y;
     76       DFS(y);
     77     }
     78   tr[p].ed = cnt_q;
     79 }
     80 #undef y
     81 #undef Son
     82  
     83 #define mid (l + r >> 1)
     84 #define Ls p -> ls
     85 #define Rs p -> rs
     86 #define V p -> v
     87 #define Tag p -> tag
     88 #define Len p -> len
     89 inline void push_tag(seg_node *p) {
     90   Ls -> tag += Tag, Rs -> tag += Tag;
     91   Ls -> v += 1ll * Tag * Ls -> len, Rs -> v += 1ll * Tag * Rs -> len;
     92   Tag = 0;
     93 }
     94  
     95 inline void update(seg_node *p) {
     96   V = Ls -> v + Rs -> v;
     97 }
     98  
     99 void seg_build(seg_node *&p, int l, int r) {
    100   p = ++cnt_seg, Ls = Rs = null;
    101   Len = r - l + 1;
    102   V = Tag = 0;
    103   if (l == r) return;
    104   seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r);
    105 }
    106  
    107 void seg_modify(seg_node *p, int l, int r, int L, int R, int d) {
    108   if (l == L && R == r) {
    109     Tag += d, V += 1ll * Len * d;
    110     return;
    111   }
    112   push_tag(p);
    113   if (L <= mid) seg_modify(Ls, l, mid, L, min(mid, R), d);
    114   if (mid < R) seg_modify(Rs, mid + 1, r, max(mid + 1, L), R, d);
    115   update(p);
    116 }
    117  
    118 ll seg_query(seg_node *p, int l, int r, int L, int R) {
    119   if (l == L && R == r)
    120     return V;
    121   push_tag(p);
    122   ll res = 0;
    123   if (L <= mid) res += seg_query(Ls, l, mid, L, min(mid, R));
    124   if (mid < R) res += seg_query(Rs, mid + 1, r, max(mid + 1, L), R);
    125   return res;
    126 }
    127 #undef mid
    128 #undef Ls
    129 #undef Rs
    130 #undef V
    131 #undef Tag
    132 #undef Len
    133  
    134 void work_add(int x, int y, int d) {
    135   while (tr[x].top != tr[y].top) {
    136     if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
    137     seg_modify(root, 1, n, tr[tr[x].top].st, tr[x].st, d);
    138     x = tr[tr[x].top].fa;
    139   }
    140   if (tr[x].dep < tr[y].dep) swap(x, y);
    141   seg_modify(root, 1, n, tr[y].st, tr[x].st, d);
    142 }
    143  
    144 int main() {
    145   int i, x, y, d, oper;
    146   null = cnt_seg;
    147   null -> ls = null -> rs = null;
    148   n = read();
    149   for (i = 1; i < n; ++i) {
    150     x = read() + 1, y = read() + 1;
    151     tr[y].fa = x;
    152     add_edge(x, y);
    153   }
    154   dfs(1);
    155   tr[1].top = 1;
    156   DFS(1);
    157   seg_build(root, 1, n);
    158   Q = read();
    159   while (Q--) {
    160     oper = getchar();
    161     while (oper != 'A' && oper != 'Q') oper = getchar();
    162     if (oper == 'A') {
    163       x = read() + 1, y = read() + 1, d = read();
    164       work_add(x, y, d);
    165     }
    166     else {
    167       x = read() + 1;
    168       printf("%lld
    ", seg_query(root, 1, n, tr[x].st, tr[x].ed));
    169     }
    170   }
    171   return 0;
    172 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    vue-cli + webpack 多页面实例配置优化方法
    Python Web(1):建立第一个Web项目
    C# winform用sharpGL(OpenGl)解析读取3D模型obj
    CSS outline 属性
    sqlserver查询两个值是否相等
    vue v-for(数组遍历)
    内存查看工具RAMMAP说明
    linux 入门
    linux 内核根文件系统
    linux 命令
  • 原文地址:https://www.cnblogs.com/rausen/p/4280574.html
Copyright © 2020-2023  润新知