cychester

Nowcoder 练习赛26E 树上路径 - 树剖

Description

传送门

给出一个n个点的树,1号节点为根节点,每个点有一个权值
你需要支持以下操作
1.将以u为根的子树内节点(包括u)的权值加val

2.将(u, v)路径上的节点权值加val
3.询问(u, v)路径上节点的权值两两相乘的和
 

Solution

维护 平方和与 数值和

修改 : 假如修改时有节点a, b, c, 增加t, 那么$sumsq = a^2 + b^2 + c^2 + 2*t*(a + b+c) + 3 * t^2$

所以对于所有的修改, $sumsq = sumsq + 2*t*sum + (r-l+1)*t^2$

这样平方和与数值和就可以维护了

查询只需要输出 $(sum * sum - sumsq) / 2$

 

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define ll long long
  5 #define rd read()
  6 #define lson nd << 1
  7 #define rson nd << 1 | 1
  8 using namespace std;
  9 
 10 const int N = 1e5 + 5;
 11 const ll mod = 1e9 + 7;
 12 
 13 int n, m;
 14 int top[N], size[N], son[N], f[N], dep[N], cnt;
 15 int head[N], tot;
 16 int A[N], a[N], id[N];
 17 int Li[N << 2], Ri[N << 2];
 18 ll sum[N << 2], sum2[N << 2], inv, add[N << 2];
 19 
 20 struct edge{
 21     int nxt, to;
 22 }e[N << 1];
 23 
 24 int read() {
 25     int X = 0, p = 1; char c = getchar();
 26     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
 27     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
 28     return X * p;
 29 }
 30 
 31 void added(int u, int v) {
 32     e[++tot].to = v;
 33     e[tot].nxt = head[u];
 34     head[u] = tot;
 35 }
 36 
 37 void dfs1(int u) {
 38     size[u] = 1;
 39     for(int i = head[u]; i; i = e[i].nxt) {
 40         int nt = e[i].to;
 41         if(nt == f[u]) continue;
 42         dep[nt] = dep[u] + 1;
 43         f[nt] = u;
 44         dfs1(nt);
 45         size[u] += size[nt];
 46         if(size[nt] > size[son[u]]) son[u] = nt;
 47     }
 48 }
 49 
 50 void dfs2(int u) {
 51     id[u] = ++cnt;
 52     A[cnt] = a[u];
 53     if(!son[u]) return;
 54     top[son[u]] = top[u];
 55     dfs2(son[u]);
 56     for(int i = head[u]; i; i = e[i].nxt) {
 57         int nt = e[i].to;
 58         if(nt == f[u] || nt == son[u]) continue;
 59         top[nt] = nt;
 60         dfs2(nt);
 61     }
 62 }
 63 
 64 void pushdown(int nd) {
 65     if(add[nd]) {
 66         sum2[lson] += (2 * sum[lson] * add[nd] % mod + (Ri[lson] - Li[lson] + 1) * add[nd] % mod * add[nd] % mod) % mod;
 67         sum2[lson] %= mod;
 68         sum2[rson] += (2 * sum[rson] * add[nd] % mod + (Ri[rson] - Li[rson] + 1) * add[nd] % mod * add[nd] % mod) % mod;
 69         sum2[rson] %= mod;
 70         
 71         sum[lson] += (Ri[lson] - Li[lson] + 1) * add[nd] % mod;
 72         sum[lson] %= mod;
 73         sum[rson] += (Ri[rson] - Li[rson] + 1) * add[nd] % mod;
 74         sum[rson] %= mod;
 75 
 76         add[lson] += add[nd];
 77         add[rson] += add[nd];
 78         add[lson] %= mod;
 79         add[rson] %= mod;
 80         add[nd] = 0;
 81     }
 82 }
 83 
 84 void update(int nd) {
 85     sum[nd] = (sum[lson] + sum[rson]) % mod;
 86     sum2[nd] = (sum2[lson] + sum2[rson]) % mod;
 87 }
 88 
 89 void build(int l, int r, int nd) {
 90     if(l == r) {
 91         Li[nd] = l;
 92         Ri[nd] = r;
 93         sum[nd] = A[l];
 94         sum2[nd] = A[l] * A[l] % mod;
 95         return;
 96     }
 97     Li[nd] = l;
 98     Ri[nd] = r;
 99     int mid =(l + r) >> 1;
100     build(l, mid, lson);
101     build(mid + 1, r, rson);
102     update(nd);
103 }
104 
105 void modify(int L, int R, int d, int l, int r, int nd) {
106     if(L <= l && r <= R) {
107         sum2[nd] += (2 * sum[nd] * d % mod + (r - l + 1) * d % mod * d % mod) % mod;
108         sum2[nd] %= mod;
109         sum[nd] += 1LL * d * (r - l + 1) % mod;
110         sum[nd] %= mod;
111         add[nd] += d;
112         add[nd] %= mod;
113         return;
114     }
115     pushdown(nd);
116     int mid = (l + r) >> 1;
117     if(mid >= L) modify(L, R, d, l, mid, lson);
118     if(mid < R) modify(L, R, d, mid + 1, r, rson);
119     update(nd);
120 }
121 
122 ll query(int L, int R, int l, int r, int nd) {
123     if(L <= l && r <= R) return sum[nd];
124     int mid = (l + r) >> 1;
125     ll re = 0;
126     pushdown(nd);
127     if(mid >= L) re = (re + query(L, R, l, mid, lson)) % mod;
128     if(mid < R) re = (re + query(L, R, mid + 1, r, rson)) % mod;
129     return re;
130 }
131 
132 ll query2(int L, int R, int l, int r, int nd) {
133     if(L <= l && r <= R) return sum2[nd];
134     int mid = (l + r) >> 1;
135     ll re = 0;
136     pushdown(nd);
137     if(mid >= L) re = (re + query2(L, R, l, mid, lson)) % mod;
138     if(mid < R) re = (re + query2(L, R, mid + 1, r, rson)) % mod;
139     return re;
140 }
141 
142 ll query_po(int x, int y) {
143     ll re = 0, tmp, sum = 0;
144     for(; top[x] != top[y];) {
145         if(dep[top[x]] < dep[top[y]]) swap(x, y);
146         tmp = query(id[top[x]], id[x], 1, n, 1);
147         sum = (sum + tmp % mod) % mod;
148         tmp = query2(id[top[x]], id[x], 1, n, 1);
149         re = (re - tmp) % mod;
150         x = f[top[x]];
151     }
152     if(dep[x] < dep[y]) swap(x, y);
153     tmp = query(id[y], id[x], 1, n, 1);
154     sum = (sum + tmp) % mod;
155     tmp = query2(id[y], id[x], 1, n, 1);
156     re = (re - tmp) % mod;
157     re = (re + sum * sum % mod) % mod;
158     re = (re % mod + mod) % mod;
159     re = re * inv % mod;
160     return re;
161 }
162 
163 void modify_po(int x, int y, int d) {
164     for(; top[x] != top[y];) {
165         if(dep[top[x]] < dep[top[y]]) swap(x, y);
166         modify(id[top[x]], id[x], d, 1, n, 1);
167         x = f[top[x]];
168     }
169     if(dep[x] < dep[y]) swap(x, y);
170     modify(id[y], id[x], d, 1, n, 1);
171 }
172 
173 ll fc(ll ta, ll b) {
174     ll re = 0;
175     for(; b; b >>= 1, ta = (ta + ta) % mod) if( b & 1) re = (re + ta) % mod;
176     return re;
177 }
178 
179 ll fpow(ll ta, ll b) {
180     ll re = 1;
181     for(; b; b >>= 1, ta = fc(ta, ta)) if(b & 1) re = fc(re, ta);
182     return re;
183 }
184 
185 int main()
186 {
187     n = rd; m = rd;
188     for(int i = 1; i <= n; ++i) a[i] = rd;
189     for(int i = 1; i < n; ++i) {
190         int u = rd, v = rd;
191         added(u, v); added(v, u);
192     }
193     dfs1(1); 
194     top[1] = 1;
195     dfs2(1);
196     build(1, n, 1);
197     inv = fpow(2, mod - 2);
198     for(int i = 1; i <= m; ++i) {
199         int k = rd;
200         if(k == 1) {
201             int u = rd, val = rd;
202             modify(id[u], id[u] + size[u] - 1, val, 1, n, 1);
203         }
204         if(k == 2) {
205             int u = rd, v = rd, val = rd;
206             modify_po(u, v, val);
207         }
208         if(k == 3) {
209             int u = rd, v = rd;
210             printf("%lld\n", query_po(u, v));
211         }
212     }
213 }
View Code

 

posted on 2018-09-08 08:29  cychester  阅读(212)  评论(0编辑  收藏  举报

导航