codeforces 916 E. Jamie and Tree

可以这很省选模拟题

首先可以想到一个神奇的做法

对于换根和子树操作,可以用ETT维护dfs序实现

对于查询lca,可以用LCT维护动态树实现

当然这不太可写,不妨优化一下

查询lca可以看成是求出lca(root,u),lca(root,v),设它们为lca1, lca2

如果lca1 == lca2,则lca为lca(u,v)

否则lca为lca1和lca2中深度最大的那个

画个图可以明显直观的得到如上结论

发现树的形态没有改变,只是换根,那么可以讨论一下root和p的关系实现子树操作

如果p是root,那么就是1~n

如果p在root内或者不与root相交,那么就是dfs序上dfn[p]~dfn[p]+sz[p]-1

如果p在root外,要计算一下root到p的路径上p的儿子x,那么就是dfs序上1~n减去dfn[x]~dfn[x]+sz[x]-1

树状数组维护区间加、区间求和

  1 %:pragma GCC optimize(2)
  2 %:pragma GCC optimize(3)
  3 %:pragma GCC optimize("Ofast")
  4 %:pragma GCC optimize("inline")
  5 %:pragma GCC optimize("-fgcse")
  6 %:pragma GCC optimize("-fgcse-lm")
  7 %:pragma GCC optimize("-fipa-sra")
  8 %:pragma GCC optimize("-ftree-pre")
  9 %:pragma GCC optimize("-ftree-vrp")
 10 %:pragma GCC optimize("-fpeephole2")
 11 %:pragma GCC optimize("-ffast-math")
 12 %:pragma GCC optimize("-fsched-spec")
 13 %:pragma GCC optimize("unroll-loops")
 14 %:pragma GCC optimize("-falign-jumps")
 15 %:pragma GCC optimize("-falign-loops")
 16 %:pragma GCC optimize("-falign-labels")
 17 %:pragma GCC optimize("-fdevirtualize")
 18 %:pragma GCC optimize("-fcaller-saves")
 19 %:pragma GCC optimize("-fcrossjumping")
 20 %:pragma GCC optimize("-fthread-jumps")
 21 %:pragma GCC optimize("-funroll-loops")
 22 %:pragma GCC optimize("-fwhole-program")
 23 %:pragma GCC optimize("-freorder-blocks")
 24 %:pragma GCC optimize("-fschedule-insns")
 25 %:pragma GCC optimize("inline-functions")
 26 %:pragma GCC optimize("-ftree-tail-merge")
 27 %:pragma GCC optimize("-fschedule-insns2")
 28 %:pragma GCC optimize("-fstrict-aliasing")
 29 %:pragma GCC optimize("-fstrict-overflow")
 30 %:pragma GCC optimize("-falign-functions")
 31 %:pragma GCC optimize("-fcse-skip-blocks")
 32 %:pragma GCC optimize("-fcse-follow-jumps")
 33 %:pragma GCC optimize("-fsched-interblock")
 34 %:pragma GCC optimize("-fpartial-inlining")
 35 %:pragma GCC optimize("no-stack-protector")
 36 %:pragma GCC optimize("-freorder-functions")
 37 %:pragma GCC optimize("-findirect-inlining")
 38 %:pragma GCC optimize("-fhoist-adjacent-loads")
 39 %:pragma GCC optimize("-frerun-cse-after-loop")
 40 %:pragma GCC optimize("inline-small-functions")
 41 %:pragma GCC optimize("-finline-small-functions")
 42 %:pragma GCC optimize("-ftree-switch-conversion")
 43 %:pragma GCC optimize("-foptimize-sibling-calls")
 44 %:pragma GCC optimize("-fexpensive-optimizations")
 45 %:pragma GCC optimize("-funsafe-loop-optimizations")
 46 %:pragma GCC optimize("inline-functions-called-once")
 47 %:pragma GCC optimize("-fdelete-null-pointer-checks")
 48 
 49 #include <bits/stdc++.h>
 50 using namespace std;
 51 const int N = 3e5 + 10;
 52 typedef long long ll;
 53 
 54 int n, q, w[N];
 55 
 56 int head[N], rest[N * 2], to[N * 2], tot;
 57 
 58 int pos[N], l[N], r[N]; ll val[N];
 59 
 60 void add(int u, int v) {
 61     to[++ tot] = v, rest[tot] = head[u], head[u] = tot;
 62 }
 63 
 64 int root;
 65 
 66 ll c1[N], c2[N];
 67 
 68 void bt_add(int x, ll y) {
 69     for(int i = x ; i <= n ; i += i & -i) c1[i] += y, c2[i] += x * y;
 70 }
 71 
 72 ll bt_query(int x) {
 73     ll res = 0;
 74     for(int i = x ; i ; i -= i & -i) res += (x + 1) * c1[i] - c2[i];
 75     return res;
 76 }
 77 
 78 inline void modify(int l, int r, ll x) {
 79     bt_add(l, x), bt_add(r + 1, -x);
 80 }
 81 
 82 inline ll query(int l, int r) {
 83     ll suml = val[l - 1] + bt_query(l - 1);
 84     ll sumr = val[r] + bt_query(r);
 85     return sumr - suml;
 86 }
 87 
 88 int fa[N][21], dep[N], clk;
 89 
 90 inline int gettruelca(int u, int v) {
 91     if(dep[u] < dep[v]) swap(u, v);
 92     for(int i = 18 ; ~ i ; -- i) if(dep[fa[u][i]] >= dep[v]) u = fa[u][i];
 93     if(u == v) return u;
 94     for(int i = 18 ; ~ i ; -- i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
 95     return fa[u][0];
 96 }
 97 
 98 inline bool inroot(int u) {
 99     return l[root] <= pos[u] && pos[u] <= r[root];
100 }
101 
102 int getlca(int u, int v) {
103     int lca1 = gettruelca(root, u);
104     int lca2 = gettruelca(root, v);
105     if(lca1 == lca2) return gettruelca(u, v);
106     else return dep[lca1] > dep[lca2] ? lca1 : lca2;
107 }
108 
109 void dfs(int u) {
110     l[u] = pos[u] = ++ clk;
111     val[clk] = w[u];
112     dep[u] = dep[fa[u][0]] + 1;
113     for(int i = head[u] ; i ; i = rest[i]) {
114         int v = to[i];
115         if(v == fa[u][0]) continue;
116         fa[v][0] = u;
117         dfs(v);
118     }
119     r[u] = clk;
120 }
121 
122 int getson(int gra) {
123     int u = root;
124     for(int i = 18 ; ~ i ; -- i) if(dep[fa[u][i]] > dep[gra]) u = fa[u][i];
125     return u;
126 }
127 
128 void modify(int u, int x) {
129     if(inroot(u)) {
130         if(u != root) modify(l[u], r[u], x);
131         else modify(1, n, x);
132     } else {
133         int p = getson(u);
134         if(fa[p][0] == u) {
135             modify(1, n, x), modify(l[p], r[p], -x);
136         } else {
137             modify(l[u], r[u], x);
138         }
139     }
140 }
141 
142 ll query(int u) {
143     if(inroot(u)) {
144         if(u != root)  return query(l[u], r[u]);
145         else return query(1, n);
146     } else {
147         int p = getson(u);
148         if(fa[p][0] == u) {
149             return query(1, n) - query(l[p], r[p]);
150         } else {
151             return query(l[u], r[u]);
152         }
153     }
154 }
155 
156 int main() {
157     scanf("%d%d", &n, &q);
158     for(int i = 1 ; i <= n ; ++ i) scanf("%d", &w[i]);
159     for(int i = 1, u, v ; i < n ; ++ i) {
160         scanf("%d%d", &u, &v);
161         add(u, v), add(v, u);
162     }
163     
164     root = 1;
165     dfs(1);
166     for(int j = 1 ; j <= 18 ; ++ j)
167         for(int i = 1 ; i <= n ; ++ i)
168             fa[i][j] = fa[fa[i][j - 1]][j - 1];
169     for(int i = 1 ; i <= n ; ++ i) val[i] += val[i - 1];
170     
171     for(int i = 1, op, u, v, x ; i <= q ; ++ i) {
172         scanf("%d", &op);
173         if(op == 1) {
174             scanf("%d", &root);
175         } else if(op == 2) {
176             scanf("%d%d%d", &u, &v, &x);
177             modify(getlca(u, v), x);
178         } else if(op == 3) {
179             scanf("%d", &u);
180             printf("%lld\n", query(u));
181         }
182     }
183 }
codeforces 916 E. Jamie and Tree

 

posted @ 2018-08-08 15:50  KingSann  阅读(220)  评论(0编辑  收藏  举报