Advertisement
ec1117

Centroid Again...

Dec 12th, 2020 (edited)
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.36 KB | None | 0 0
  1. /**
  2.  * Description: The centroid of a tree of size $N$ is a vertex such that
  3.     * after removing it, all resulting subtrees have size at most $\frac{N}{2}.$
  4.     * Supports updates in the form ``add 1 to all verts $v$ such that $dist(x,v)\le y$."
  5.  * Time: O(N\log N) build, O(\log N) update and query
  6.  * Memory: O(N\log N)
  7.  * Source: own
  8.  * Verification:
  9.     * solves https://dmoj.ca/problem/dmopc19c7p6
  10.     * https://codeforces.com/contest/342/problem/E
  11.     * Triway Cup 2019 G
  12.  */
  13.  
  14. void ad(vi& a, int b) { ckmin(b,sz(a)-1); if (b>=0) a[b]++; }
  15. void prop(vi& a) { R0F(i,sz(a)-1) a[i] += a[i+1]; }
  16. template<int SZ> struct Centroid {
  17.     vi adj[SZ]; void ae(int a,int b){adj[a].pb(b),adj[b].pb(a);}
  18.     bool done[SZ]; // processed as centroid yet
  19.     int N,sub[SZ],cen[SZ],lev[SZ]; // subtree size, centroid anc
  20.     int dist[32-__builtin_clz(SZ)][SZ]; // dists to all ancs
  21.     vi stor[SZ], STOR[SZ];
  22.     void dfs(int x, int p) { sub[x] = 1;
  23.         trav(y,adj[x]) if (!done[y] && y != p)
  24.             dfs(y,x), sub[x] += sub[y];
  25.     }
  26.     int centroid(int x) {
  27.         dfs(x,-1);
  28.         for (int sz = sub[x];;) {
  29.             pi mx = {0,0};
  30.             trav(y,adj[x]) if (!done[y] && sub[y] < sub[x])
  31.                 ckmax(mx,{sub[y],y});
  32.             if (mx.f*2 <= sz) return x;
  33.             x = mx.s;
  34.         }
  35.     }
  36.     void genDist(int x, int p, int lev) {
  37.         dist[lev][x] = dist[lev][p]+1;
  38.         trav(y,adj[x]) if (!done[y] && y != p) genDist(y,x,lev); }
  39.     void gen(int CEN, int _x) { // CEN = centroid above x
  40.         int x = centroid(_x); done[x] = 1; cen[x] = CEN;
  41.         sub[x] = sub[_x]; lev[x] = (CEN == -1 ? 0 : lev[CEN]+1);
  42.         dist[lev[x]][x] = 0;
  43.         stor[x].rsz(sub[x]),STOR[x].rsz(sub[x]+1);
  44.         trav(y,adj[x]) if (!done[y]) genDist(y,x,lev[x]);
  45.         trav(y,adj[x]) if (!done[y]) gen(x,y);
  46.     }
  47.     void init(int _N) { N = _N; FOR(i,1,N+1) done[i] = 0;
  48.         gen(-1,1);  } // start at vert 1
  49.     void upd(int x, int y) {
  50.         int cur = x, pre = -1;
  51.         R0F(i,lev[x]+1) {
  52.             ad(stor[cur],y-dist[i][x]);
  53.             if (pre != -1) ad(STOR[pre],y-dist[i][x]);
  54.             if (i > 0) pre = cur, cur = cen[cur];
  55.         }
  56.     } // call propAll() after all updates
  57.     void propAll() { FOR(i,1,N+1) prop(stor[i]), prop(STOR[i]); }
  58.     int query(int x) { // get value at vertex x
  59.         int cur = x, pre = -1, ans = 0;
  60.         R0F(i,lev[x]+1) { // if pre != -1, subtract those from
  61.             ans += stor[cur][dist[i][x]]; // same subtree
  62.             if (pre != -1) ans -= STOR[pre][dist[i][x]];
  63.             if (i > 0) pre = cur, cur = cen[cur];
  64.         }
  65.         return ans;
  66.     }
  67. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement