首页 > 其他 > 详细

BZOJ2836 魔法树

时间:2015-02-08 23:11:05      阅读:397      评论:0      收藏:0      [点我收藏+]

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

(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\n", seg_query(root, 1, n, tr[x].st, tr[x].ed));
169     }
170   }
171   return 0;
172 }
View Code

 

BZOJ2836 魔法树

原文:http://www.cnblogs.com/rausen/p/4280574.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!