LG7124 [Ynoi2008] stcm【樹分治,構造】
阿新 • • 發佈:2021-07-12
大概是全域性平衡二叉樹的思想(
假設當前遞迴到處理 \(x\) 的子樹,首先我們先把以 \(x\) 為鏈頂的重鏈上的節點做了,因為這些集合互相包含,可以全部加一次再刪掉。
接著要遞迴到輕子樹,首先把重鏈節點加入,然後對輕子樹建 Huffman 樹,“加左進右,加右進左”,就可以對每個輕子樹都把它以外的節點加入,遞迴到輕兒子。
加點操作次數是 \(2.5n\log n\),可以過。
#include<bits/stdc++.h> #define PB emplace_back #define fi first #define se second using namespace std; template<typename Functor> struct wrapper_type { Functor functor; template<typename... Args> decltype(auto) operator()(Args&&... args) const& { return functor(functor, std::forward<Args>(args)...); } }; template<typename Functor> wrapper_type<typename std::decay<Functor>::type> wrapper(Functor&& functor) { return{ std::forward<Functor>(functor) }; } typedef pair<int, int> pii; const int N = 100003; int n, fa[N], son[N], siz[N]; vector<int> E[N]; void dfs(int x){ siz[x] = 1; for(int v : E[x]){ dfs(v); siz[x] += siz[v]; if(siz[son[x]] < siz[v]) son[x] = v; } } void add(int x){printf("+%d", x); for(int v : E[x]) add(v);} void rem(int x){while(x --) putchar('-');} void work(int x){ priority_queue<pii, vector<pii>, greater<pii> > pq; int len = 0; for(int u = x;u;u = son[u]){ printf("=%d+%d", u, u); ++len; for(int v : E[u]) if(v != son[u]){ add(v); pq.emplace(siz[v], v); } } rem(siz[x]); if(pq.empty()) return; for(int u = x;u;u = son[u]) printf("+%d", u); vector<int> sum, ls, rs; while(pq.size() > 1){ pii L = pq.top(); pq.pop(); pii R = pq.top(); pq.pop(); sum.PB(L.fi + R.fi); ls.PB(L.se); rs.PB(R.se); pq.emplace(L.fi + R.fi, n + sum.size()); } auto S = [&](int x){return x <= n ? siz[x] : sum[x-n-1];}; auto Add = wrapper([&](auto&& self, int x) -> void{ if(x <= n) add(x); else {x -= n+1; self(self, ls[x]); self(self, rs[x]);} }); auto Work = wrapper([&](auto&& self, int x) -> void{ if(x <= n) work(x); else { x -= n+1; Add(ls[x]); self(self, rs[x]); rem(S(ls[x])); Add(rs[x]); self(self, ls[x]); rem(S(rs[x])); } }); Work(pq.top().se); rem(len); } void solve(){ for(int i = 1;i <= n;++ i) E[i].resize(0); memset(son, 0, n+1<<2); for(int i = 2;i <= n;++ i){ scanf("%d", fa+i); E[fa[i]].PB(i); } dfs(1); work(1); puts("!"); } int main(){while(~scanf("%d", &n)) solve();}
這他媽都什麼語法糖啊(