Submission #1043580

#TimeUsernameProblemLanguageResultExecution timeMemory
1043580jcelinRadio Towers (IOI22_towers)C++17
100 / 100
1053 ms182036 KiB
#pragma once #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> ii; typedef pair<ll,ll> pll; typedef vector<int> vi; typedef vector<ii> vii; typedef vector<ll> vll; typedef vector<pll> vpll; #define PB push_back #define PF push_front #define PPB pop_back #define PPF pop_front #define X first #define Y second #define MP make_pair #define all(x) (x).begin(), (x).end() const int mod = 1e9 + 7; //998244353; const int inf = (1 << 30) - 1; const ll INF = (1ll << 62) - 1; const int logo = 17; const int MAXN = 1e5 + 7; const int off = 1 << logo; const int trsz = off << 1; const int dx[] = {1, -1, 0, 0}; const int dy[] = {0, 0, -1, 1}; struct tour{ int seg[trsz]; void update(int x, int vl){ x += off; seg[x] = vl; for(x /= 2; x; x /= 2) seg[x] = max(seg[x * 2], seg[x * 2 + 1]); } int query(int l, int r){ int ret = 0; for(l += off, r += off; l < r; l >>= 1, r >>= 1){ if(l & 1) ret = max(ret, seg[l++]); if(r & 1) ret = max(ret, seg[--r]); } return ret; } int spusti(int x, int vl, bool fl){ if(x >= off) return x - off; int pr = x * 2; if(fl) pr = x * 2 + 1; if(seg[pr] >= vl) return spusti(pr, vl, fl); return spusti(pr ^ 1, vl, fl); } int nadi(int l, int r, int vl, int fl){ vi lef, rig; for(l += off, r += off; l < r; l >>= 1, r >>= 1){ if(l & 1) lef.PB(l++); if(r & 1) rig.PB(--r); } while(rig.size()) lef.PB(rig.back()), rig.PPB(); int ans = 0; if(fl == 0){ for(auto &x : lef){ if(ans == 0 and seg[x] >= vl) ans = spusti(x, vl, 0); } }else{ for(auto it = lef.rbegin(); it != lef.rend(); it++){ if(ans == 0 and seg[*it] >= vl) ans = spusti(*it, vl, 1); } } return ans; } }t; struct tdelta{ struct node{ int v1, v2, ret1, ret2; node(){ v1 = inf, v2 = -inf, ret1 = 0, ret2 = 0; } }; node seg[trsz]; node merge(node a, node b){ node c; c.v1 = min(a.v1, b.v1); c.v2 = max(a.v2, b.v2); c.ret1 = max(a.ret1, b.ret1); c.ret1 = max(c.ret1, b.v2 - a.v1); c.ret2 = max(a.ret2, b.ret2); c.ret2 = max(c.ret2, a.v2 - b.v1); return c; } void update(int x, int vl){ x += off; seg[x].v1 = seg[x].v2 = vl; for(x /= 2; x; x /= 2) seg[x] = merge(seg[x * 2], seg[x * 2 + 1]); } ii query(int l, int r){ if(l > r) return {0, 0}; node ret; vi lef, rig; for(l += off, r += off; l < r; l >>= 1, r >>= 1){ if(l & 1) lef.PB(l++); if(r & 1) rig.PB(--r); } while(rig.size()) lef.PB(rig.back()), rig.PPB(); for(auto &x : lef) ret = merge(ret, seg[x]); return {ret.ret1, ret.ret2}; } int cm ; int spusti(int x, int vl){ if(x >= off) return x - off; if(seg[x * 2].ret1 >= vl or seg[x * 2].v2 - cm >= vl) return spusti(x * 2, vl); cm = min(cm, seg[x * 2].v1); return spusti(x * 2 + 1, vl); } int nadi(int l, int r, int vl){ vi lef, rig; for(l += off, r += off; l < r; l >>= 1, r >>= 1){ if(l & 1) lef.PB(l++); if(r & 1) rig.PB(--r); } while(rig.size()) lef.PB(rig.back()), rig.PPB(); cm = inf; int ret = inf; for(auto &x : lef){ if(seg[x].ret1 >= vl or seg[x].v2 - cm >= vl){ ret = spusti(x, vl); return ret; } cm = min(cm, seg[x].v1); } return ret; } }del; bool submit; struct per{ struct node{ node *L, *R; int cnt, mi, mx; node(){ L = R = 0; cnt = mi = mx = 0; } node(node *_L, node *_R, int _cnt, int _mi, int _mx){ L = _L, R = _R, cnt = _cnt, mi = _mi, mx = _mx; } }; typedef node* pnode; pnode rt[MAXN]; set<pnode> st; pnode l(pnode x){return x ? x -> L : 0;} pnode r(pnode x){return x ? x -> R : 0;} int c(pnode x){return x ? x -> cnt : 0;} int sm(pnode x){return x ? x -> mi : 0;} int bg(pnode x){return x ? x -> mx : 0;} void update(pnode &x, int lo, int hi, int a, int b, int vl){ if(lo >= b or hi <= a) return; if(!submit) st.insert(x); x = new node(l(x), r(x), c(x), sm(x), bg(x)); if(!submit) st.insert(x); if(lo >= a and hi <= b){ if(vl){ x -> cnt = 1; x -> mi = lo; x -> mx = lo; }else{ x -> cnt = 0; x -> mi = inf; x -> mx = -inf; } return; } int mid = (lo + hi) / 2; update(x -> L, lo, mid, a, b, vl); update(x -> R, mid, hi, a, b, vl); x -> mi = min(sm(x -> L), sm(x -> R)); x -> mx = max(bg(x -> L), bg(x -> R)); x -> cnt = c(x -> L) + c(x -> R); } int query(pnode &x, int lo, int hi, int a, int b){ if(lo >= b or hi <= a or !x) return 0; if(lo >= a and hi <= b) return c(x); int mid = (lo + hi) / 2; return query(x -> L, lo, mid, a, b) + query(x -> R, mid, hi, a, b); } ii merge(ii a, ii b){ return {min(a.X, b.X), max(a.Y, b.Y)}; } ii qry(pnode &x, int lo, int hi, int a, int b){ if(lo >= b or hi <= a or !x) return {inf, -inf}; if(lo >= a and hi <= b) return {sm(x), bg(x)}; int mid = (lo + hi) / 2; return merge(qry(x -> L, lo, mid, a, b), qry(x -> R, mid, hi, a, b)); } void update(int tim, int a, int b, int vl){ update(rt[tim], 0, off, a, b, vl); } void res(){ for(auto &x : st) delete x; st.clear(); } int query(int tim, int l, int r){ return query(rt[tim], 0, off, l, r); } ii query2(int tim, int l, int r){ return qry(rt[tim], 0, off, l, r); } }p; int pm[MAXN], pv[MAXN], vl[MAXN], arr[MAXN]; vii st; vi upd[MAXN], vals; void init(int n, vi aa){ submit = 1; for(int i=0; i<n; i++) arr[i + 1] = aa[i]; st.clear(); arr[0] = 2 * inf; arr[n + 1] = 2 * inf; t.update(0, 2 * inf); t.update(n + 1, 2 * inf); st.PB({-1, -inf}); for(int i=1; i<=n; i++){ while(st.back().Y > arr[i]) st.PPB(); pm[i] = st.back().X; st.PB({i, arr[i]}); t.update(i, arr[i]); del.update(i, arr[i]); } st.clear(); st.PB({n + 2, -inf}); for(int i=n; i; i--){ while(st.back().Y > arr[i]) st.PPB(); pv[i] = st.back().X; st.PB({i, arr[i]}); } for(int i=1; i<=n; i++){ int a = pm[i], b = pv[i]; int op = min(t.query(a + 1, i), t.query(i + 1, b)); op = max(op, arr[i]); vl[i] = op - arr[i]; vals.PB(vl[i]); } vals.PB(0); vals.PB(inf); sort(all(vals)); vals.erase(unique(all(vals)), vals.end()); for(int i=1; i<=n; i++){ vl[i] = lower_bound(all(vals), vl[i]) - vals.begin(); upd[vl[i] + 1].PB(i); } p.rt[0] = NULL; for(int i=1; i<=n; i++) p.update(0, i, i + 1, 1); for(int i=1; i<(int)vals.size(); i++){ p.rt[i] = p.rt[i - 1]; for(auto &x : upd[i]) p.update(i, x, x + 1, 0); } } int max_towers(int l, int r, int d){ l++, r++; auto it = lower_bound(all(vals), d) - vals.begin(); int lef, rig, sum = p.query(it, l, r + 1); if(sum == 0){ if(r - l + 1 >= 3){ int najl = del.nadi(l, r + 1, d); if(del.query(najl, r + 1).Y >= d) return 2; } return 1; } tie(lef, rig) = p.query2(it, l, r + 1); int opt = t.nadi(l, lef, arr[lef] + d, 1); if(opt) if(del.query(l, opt + 1).X >= d) sum++; opt = t.nadi(rig + 1, r + 1, arr[rig] + d, 0); if(opt) if(del.query(opt, r + 1).Y >= d) sum++; return sum; } void zavrsi(){ p.res(); }

Compilation message (stderr)

towers.cpp:1:9: warning: #pragma once in main file
    1 | #pragma once
      |         ^~~~
#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...