本来直接树剖就好了,但是树剖会多一个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] = '\0';
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('\n');
171 }
View Code

 

By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
posted on 2015-05-04 22:15  Xs酱~  阅读(283)  评论(1编辑  收藏  举报