Submission #1071977

#TimeUsernameProblemLanguageResultExecution timeMemory
1071977bleahbleahBeech Tree (IOI23_beechtree)C++17
100 / 100
1675 ms188244 KiB
#pragma GCC optimize("Ofast") //#pragma GCC target("avx,avx2") #include "beechtree.h" #include <bits/stdc++.h> #define all(x) (x).begin(),(x).end() using namespace std; using ll = long long; using ld = long double; //#define int ll #define sz(x) ((int)(x).size()) using pii = pair<int,int>; using tii = tuple<int,int,int>; const int nmax = 2e5 + 5; const ll mod = 998244853; struct Mint { ll val; Mint(ll x = 0): val((x % mod + mod) % mod) {;} Mint operator +(const Mint& x) const { return Mint(val + x.val); } Mint operator -(const Mint& x) const { return Mint(val - x.val); } Mint operator *(const Mint& x) const { return Mint(val * x.val); } Mint operator +=(const Mint& x) { return *this = Mint(val + x.val); } Mint operator -=(const Mint& x) { return *this = Mint(val - x.val); } Mint operator *=(const Mint& x) { return *this = Mint(val * x.val); } Mint operator ^(const int& _b) const { Mint accum = 1, a = *this; int b = _b; while(b) { accum = (b & 1? accum * a : accum); a *= a; b >>= 1; } return accum; } Mint operator /(const Mint& x) { return Mint((ll)val * (x ^ (mod - 2)).val); } Mint operator /=(const Mint& x) { return *this = Mint((ll)val * (x ^ (mod - 2)).val); } }; Mint p[2][nmax * 2]; #define hash bjsefdjhsdsfhoi struct hash { Mint v[2]; int len; hash(Mint a, Mint b, int c) { v[0] = a; v[1] = b; len = c; } hash(Mint a) { v[0] = a; v[1] = a; len = 1; } hash() { v[0] = 0; v[1] = 0; len = 0; } hash operator +(const hash& x) const { return hash(v[0] * p[0][x.len] + x.v[0], v[1] * p[1][x.len] + x.v[1], len + x.len); } hash operator -(const hash& x) const { return hash(v[0] - p[0][len - x.len] * x.v[0], v[1] - p[1][len - x.len] * x.v[1], len - x.len); } hash operator += (const hash& x) { return *this = *this + x; } hash operator -= (const hash& x) { return *this = *this - x; } bool operator !=(const hash& x) const { return v[0].val != x.v[0].val || v[1].val != x.v[1].val || len != x.len; } ll operator()() const { return (ll)v[0].val * mod + v[1].val; } bool operator < (const hash& x) const { return (*this)() < x(); } bool operator == (const hash& x) const { return (*this)() == x(); } }; vector<pii> g[nmax]; vector<pii> invg[nmax]; vector<int> P, C; bool isanc(unordered_set<int>& A, unordered_set<int>& B) { if(sz(A) < sz(B)) return 0; for(auto &x : B) if(!A.count(x)) return 0; return 1; } vector<int> sol; int area[nmax], pin[nmax], pout[nmax], inp; hash eulerH[2 * nmax], dH[nmax]; pii euler[2 * nmax]; int poz; void init(int node) { sort(all(g[node]), [&](auto a, auto b) { return a.second < b.second; }); euler[++poz] = pii{node, 0}; eulerH[poz] = eulerH[poz - 1] + hash(2 * C[node] + 0); pin[node] = poz + 1; area[node] = 1; for(auto [x, c] : g[node]) dH[x] = dH[node] + hash(c), init(x), area[node] += area[x]; pout[node] = poz; euler[++poz] = pii{node, 1}; eulerH[poz] = eulerH[poz - 1] + hash(2 * C[node] + 1); } vector<int> difference(int node, int other) { vector<int> ass_list; auto getL = [&](int l, int r) { return eulerH[r + pin[node]] - eulerH[l + pin[node] - 1]; }; auto getR = [&](int l, int r) { return eulerH[r + pin[other]] - eulerH[l + pin[other] - 1]; }; auto visit = [&](auto&& self, int nod, int& r) -> void { r++; ass_list.emplace_back(nod); for(auto [x, c] : g[nod]) self(self, x, r); r++; }; int l0 = 0, r0 = 0, END0 = pout[node] - pin[node] + 1, l1 = 0, r1 = 0, END1 = pout[other] - pin[other] + 1; while(l0 < END0 && l1 < END1) { r0 = l0 - 1, r1 = l1 - 1; for(int lim = 1 << 18; lim > 0; lim >>= 1) { if(r0 + lim < END0 && r1 + lim < END1 && getL(l0, r0 + lim)() == getR(l1, r1 + lim)()) r0 += lim, r1 += lim; } if(r0 == END0 - 1 || r1 == END1 - 1); else { auto [nxt0, t0] = euler[pin[node] + r0 + 1]; auto [nxt1, t1] = euler[pin[other] + r1 + 1]; if(t1 == 0 && C[nxt1] < C[nxt0]) return {-1}; if(t0 == 1) return {-1}; visit(visit, nxt0, r0); } l0 = r0 + 1; l1 = r1 + 1; } if(l0 == END0 && l1 < END1) return {-1}; while(l0 < END0) { auto [nxt0, t0] = euler[pin[node] + l0]; visit(visit, nxt0, l0); } return ass_list; } #define erset set bool coaielemele; struct PartDiff { map<int, erset<hash>> onlevel; map<hash, int> inverse; int feasable = 1; void add(int dim, int prevdim, erset<hash> ths) { if(!feasable) return; bool coaiee = coaielemele; if(onlevel.count(dim)) { for(auto x : ths) { if(inverse.count(x) == 0) {feasable = 0; return; } if(inverse[x] > dim) {feasable = 0; return; } } } else { auto it = onlevel.upper_bound(dim); int bigger = -1; if(it == onlevel.end()); else bigger = it -> first; it = onlevel.upper_bound(prevdim); while(!ths.empty() && it != onlevel.end() && it -> first < dim) { for(auto x : it -> second) { if(ths.count(x)) { ths.erase(x); } else { feasable = 0; return; } } it = next(it); } for(auto x : ths) { if(inverse.count(x) == 0) { if(bigger == -1) { ; } else { feasable = 0; return; } } else { if(inverse[x] > dim) { if(inverse[x] == bigger) { onlevel[bigger].erase(x); } // o sa il pun, dar n-are ce cauta aici else { feasable = 0; return; } // prost } else { assert(inverse[x] < dim); if(inverse[x] > prevdim) { continue; } // nu vreau sa il pun else { feasable = 0; return; } // prost } } onlevel[dim].emplace(x); inverse[x] = dim; } } } void add(PartDiff& x) { if(!feasable) return; if(!x.feasable) { feasable = 0; return; } if(sz(x.inverse) > sz(inverse)) swap(x, *this); int prv = -1; for(auto [h, v] : x.onlevel) { add(h, prv, v); prv = h; } x.onlevel.clear(); x.inverse.clear(); return; } }; void print(int node) { } PartDiff dfs(int node) { PartDiff mine; int heavyson = -1; coaielemele = 0; for(auto &[x, c] : g[node]) { auto T = dfs(x); mine.add(T); if(heavyson == -1 || area[x] > area[heavyson]) heavyson = x; } coaielemele = 0; if(sz(g[node]) != sz(invg[node])) { mine.feasable = sol[node] = 0; return mine; } if(mine.feasable == 0) { sol[node] = 0; return mine; } if(heavyson == -1) { erset<hash> pl; pl.emplace(hash()); mine.add(1, -1, pl); } else { auto sons = difference(node, heavyson); //vector<int> sons; //for(auto [a, b] : g[node]) sons.emplace_back(a); if(sz(sons) && sons[0] == -1) { mine.feasable = sol[node] = 0; return mine; } erset<hash> pl; for(auto x : sons) pl.emplace(dH[x] - dH[node]); mine.add(area[node], area[heavyson], pl); } sol[node] = mine.feasable = mine.feasable && (sz(mine.inverse) == area[node]); return mine; } std::vector<int> beechtree(int N, int M, std::vector<int> P_, std::vector<int> C_) { mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); p[0][0] = p[1][0] = 1; p[0][1] = rng() % (mod - 1000) + 503; #ifdef DLOCAL p[0][1] = 100000; #endif p[1][1] = rng() % (mod - 1200) + 505; for(int i = 2; i < nmax; i++) p[0][i] = p[0][i - 1] * p[0][1], p[1][i] = p[1][i - 1] * p[1][1]; P = P_; C = C_; for(int i = 1; i < N; i++) { g[P[i]].emplace_back(i, C[i]); invg[P[i]].emplace_back(C[i], -1); } for(int i = 0; i < N; i++) sort(all(invg[i])), invg[i].erase(unique(all(invg[i])), end(invg[i])); sol.assign(N, 0); init(0); dfs(0); return sol; } /** Töte es durch genaue Untersuchung\Töte es kann es nur noch schlimmer machen\Es lässt es irgendwie atmen -- */

Compilation message (stderr)

beechtree.cpp: In member function 'void PartDiff::add(int, int, std::set<bjsefdjhsdsfhoi>)':
beechtree.cpp:160:12: warning: unused variable 'coaiee' [-Wunused-variable]
  160 |       bool coaiee = coaielemele;
      |            ^~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...