Submission #630200

#TimeUsernameProblemLanguageResultExecution timeMemory
630200qwerasdfzxclRadio Towers (IOI22_towers)C++17
100 / 100
1367 ms51488 KiB
#include "towers.h" #include <bits/stdc++.h> using namespace std; typedef long long ll; int n, a[100100], b[100100], typ[100100]; vector<int> T; struct Node{ int x, l, r; Node(){} Node(int _x, int _l, int _r): x(_x), l(_l), r(_r) {} }; struct PST{ Node tree[4004000]; int root[100100], pt1, pt2, sz; void init(int n){ sz = n; tree[0] = Node(0, -1, -1); root[0] = 0; pt1 = 1, pt2 = 1; } void add(){ tree[pt1] = tree[root[pt2-1]]; root[pt2] = pt1; ++pt1, ++pt2; } int _new(int i){ if (i!=-1) tree[pt1++] = tree[i]; else tree[pt1++] = Node(0, -1, -1); return pt1-1; } void build(int i, int l, int r, int a[]){ if (l==r) {tree[i].x = a[l]; return;} int m = (l+r)>>1; tree[i].l = _new(tree[i].l); tree[i].r = _new(tree[i].r); build(tree[i].l, l, m, a); build(tree[i].r, m+1, r, a); tree[i].x = tree[tree[i].l].x + tree[tree[i].r].x; } void update(int i, int l, int r, int s, int x){ if (r<s || s<l) return; if (l==r) {tree[i].x = x; return;} int m = (l+r)>>1; tree[i].l = _new(tree[i].l); tree[i].r = _new(tree[i].r); update(tree[i].l, l, m, s, x); update(tree[i].r, m+1, r, s, x); tree[i].x = tree[tree[i].l].x + tree[tree[i].r].x; } int query(int i, int l, int r, int s, int e){ if (i==-1) return 0; if (r<s || e<l) return 0; if (s<=l && r<=e) return tree[i].x; int m = (l+r)>>1; return query(tree[i].l, l, m, s, e) + query(tree[i].r, m+1, r, s, e); } int left_bound(int i, int l, int r, int s, int e){ if (r<s || e<l) return -1; if (tree[i].x==0) return -1; if (l==r) return l; int m = (l+r)>>1; int tmp = left_bound(tree[i].l, l, m, s, e); if (tmp!=-1) return tmp; return left_bound(tree[i].r, m+1, r, s, e); } int right_bound(int i, int l, int r, int s, int e){ if (r<s || e<l) return -1; if (tree[i].x==0) return -1; if (l==r) return l; int m = (l+r)>>1; int tmp = right_bound(tree[i].r, m+1, r, s, e); if (tmp!=-1) return tmp; return right_bound(tree[i].l, l, m, s, e); } void update(int s, int x){ update(root[pt2-1], 1, sz, s, x); } int query(int t, int l, int r){ return query(root[t], 1, sz, l, r); } int left_bound(int t, int l, int r){ return left_bound(root[t], 1, sz, l, r); } int right_bound(int t, int l, int r){ return right_bound(root[t], 1, sz, l, r); } }tree1; struct Seg{ int tree[200200], sz; void init(int n){ sz = n; for (int i=sz;i<sz*2;i++) tree[i] = a[i-sz]; for (int i=sz-1;i;i--) tree[i] = min(tree[i<<1], tree[i<<1|1]); } int query(int l, int r){ ++r; int ret = 1e9; for (l+=sz, r+=sz;l<r;l>>=1, r>>=1){ if (l&1) ret = min(ret, tree[l++]); if (r&1) ret = min(ret, tree[--r]); } return ret; } }tree2; set<int> st; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; int myabs(int x){ if (x<0) return -x; return x; } int getd(int x){ auto iter = st.find(x); if (iter==st.end() || next(iter)==st.end()) return -1; return myabs(a[*next(iter)] - a[*iter]); } void init(int N, std::vector<int> H) { n = N; for (int i=1;i<=n;i++) a[i] = H[i-1]; int tl = 1, tr = n; for (;tl<n;tl++) if (a[tl] < a[tl+1]) break; for (;tr>1;tr--) if (a[tr-1] > a[tr]) break; assert(tl<=tr); st.insert(tl); st.insert(tr); b[tl] = b[tr] = 1; typ[tl] = typ[tr] = -1; for (int i=tl+1;i<tr;i++){ if (a[i-1] < a[i] && a[i] > a[i+1]){ b[i] = 1, typ[i] = 1; st.insert(i); } if (a[i-1] > a[i] && a[i] < a[i+1]){ b[i] = 1, typ[i] = -1; st.insert(i); } } for (auto iter=st.begin();next(iter)!=st.end();iter++) pq.emplace(myabs(a[*next(iter)] - a[*iter]), *iter); tree1.init(n); tree1.build(0, 1, n, b); tree2.init(n+1); T.push_back(0); while(!pq.empty()){ auto [d, i] = pq.top(); pq.pop(); if (getd(i)!=d) continue; auto iter = st.find(i); T.push_back(d); tree1.add(); tree1.update(i, 0); tree1.update(*next(iter), 0); iter = st.erase(iter, next(next(iter))); //for (auto &x:st) printf(" %d", x); //printf("\n"); if (iter==st.begin() || iter==st.end()) continue; //printf(" add: %d %d -> %d\n", *prev(iter), *iter, getd(*prev(iter))); --iter; pq.emplace(myabs(a[*next(iter)] - a[*iter]), *iter); } /*for (int i=1;i<=n;i++) printf("%d ", b[i]); printf("\n"); for (int i=1;i<=n;i++) printf("%d ", typ[i]); printf("\n"); for (auto &x:T) printf("%d ", x); printf("\n");*/ //printf("%d\n", tree1.tree[0].x); } int max_towers(int l, int r, int D) { ++l, ++r; int t = lower_bound(T.begin(), T.end(), D) - T.begin() - 1; int ans = tree1.query(t, l, r); //printf("%d -> ", ans); if (ans==0) return 1; int L = tree1.left_bound(t, l, r), R = tree1.right_bound(t, l, r); assert(L!=-1); assert(R!=-1); if (typ[L]==1){ int tmp = tree2.query(l, L-1); if (a[L] - tmp >= D) ans++; else ans--; } if (ans==0) return 1; if (typ[R]==1){ int tmp = tree2.query(R+1, r); if (a[R] - tmp >= D) ans++; else ans--; } assert(ans%2==1); return (ans+1)/2; }
#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...