Submission #1221221

#TimeUsernameProblemLanguageResultExecution timeMemory
1221221steveonalexRadio Towers (IOI22_towers)C++20
100 / 100
497 ms75488 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned int ul; typedef unsigned long long ull; #define MASK(i) (1ULL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll gcd(ll a, ll b){return __gcd(abs(a), abs(b));} ll lcm(ll a, ll b){return abs(a) / gcd(a, b) * abs(b);} ll LASTBIT(ll mask){return (mask) & (-mask);} int pop_cnt(ull mask){return __builtin_popcountll(mask);} int ctz(ull mask){return __builtin_ctzll(mask);} int logOf(ull mask){return 63 - __builtin_clzll(mask);} mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); ll rngesus(ll l, ll r){return l + (ull) rng() % (r - l + 1);} template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){ for(auto item: container) out << item << separator; out << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } #include "towers.h" const int INF = 1e9 + 69; struct SegmentTree{ int n; vector<pair<int,int>> a; SegmentTree(int _n = 0){ n = _n; a.resize(n * 2 + 2, {-INF, -INF}); } void update(int i, int v){ i += n; a[i] = make_pair(v, i - n); while(i > 1){ i >>= 1; a[i] = max(a[i * 2], a[i * 2 + 1]); } } pair<int, int> get(int l, int r){ l += n; r += n + 1; pair<int, int> ans = make_pair(-INF, -INF); while(l < r){ if (l & 1) maximize(ans, a[l++]); if (r & 1) maximize(ans, a[--r]); l >>= 1; r >>= 1; } return ans; } }; const int N = MASK(17); struct Persistent{ struct Node{ int child[2]; int sum; Node(){ memset(child, 0, sizeof child); sum = 0; } }; static const int L = 1, R = N; vector<Node> a; vector<int> root_stack; void add_node(int &x){ x = a.size(); a.emplace_back(); } Persistent(){ a.emplace_back(); a.emplace_back(); root_stack.push_back(1); } int get_cur_version(){ return root_stack.size() - 1; } void update(int i, int v, int l, int r, int prev_id, int id){ a[id] = a[prev_id]; a[id].sum += v; if (l == r) return; int mid = (l + r) >> 1; if (i <= mid){ add_node(a[id].child[0]); update(i, v, l, mid, a[prev_id].child[0], a[id].child[0]); } else{ add_node(a[id].child[1]); update(i, v, mid + 1, r, a[prev_id].child[1], a[id].child[1]); } } void update(int i, int v){ int prev_id = root_stack.back(); int id; add_node(id); root_stack.push_back(id); update(i, v, L, R, prev_id, id); } int get(int u, int v, int l, int r, int id){ if (u <= l && r <= v) return a[id].sum; int mid = (l + r) >> 1; int ans = 0; if (u <= mid) ans += get(u, v, l, mid, a[id].child[0]); if (v > mid) ans += get(u, v, mid+1, r, a[id].child[1]); return ans; } int get(int l, int r, int version){ return get(l, r, L, R, root_stack[version]); } int walk_left(int i, int l, int r, int id){ if (r < i) return -1; if (a[id].sum == 0) return -1; if (l == r) return l; int mid = (l + r) >> 1; int left = walk_left(i, l, mid, a[id].child[0]); if (left != -1) return left; return walk_left(i, mid+1, r, a[id].child[1]); } int walk_left(int i, int version){ return walk_left(i, L, R, root_stack[version]); } int walk_right(int i, int l, int r, int id){ if (l > i) return -1; if (a[id].sum == 0) return -1; if (l == r) return l; int mid = (l + r) >> 1; int right = walk_right(i, mid+1, r, a[id].child[1]); if (right != -1) return right; return walk_right(i, l, mid, a[id].child[0]); } int walk_right(int i, int version){ return walk_right(i, L, R, root_stack[version]); } }; int n; vector<int> a; SegmentTree st1, st2; vector<pair<int, int>> subtract_op, plus_op; vector<int> X; vector<pair<int,int>> packets[N * 4]; Persistent pst; int version_at[N * 4]; void dnc(int l, int r){ if (l > r) return; int mid = st1.get(l, r).second; dnc(l, mid-1); dnc(mid+1, r); int cur_ma = st1.get(l, r).first; if (mid > l){ int left_ma = st1.get(l, mid-1).first; int left_mi = -st2.get(l, mid-1).first; int left_pos = st2.get(l, mid-1).second; plus_op.push_back(make_pair(left_ma - left_mi + 1, left_pos)); subtract_op.push_back(make_pair(cur_ma - left_mi + 1, left_pos)); } if (mid < r){ int right_ma = st1.get(mid+1, r).first; int right_mi = -st2.get(mid+1, r).first; int right_pos = st2.get(mid+1, r).second; plus_op.push_back(make_pair(right_ma - right_mi + 1, right_pos)); subtract_op.push_back(make_pair(cur_ma - right_mi + 1, right_pos)); } } void init(int N, vector<int> H) { H.insert(H.begin(), 0); n = N; a = H; st1 = SegmentTree(n), st2 = SegmentTree(n); for(int i = 1; i <= n; ++i){ st1.update(i, a[i]); st2.update(i, -a[i]); } dnc(1, n); for(pair<int, int> i: subtract_op) X.push_back(i.first); for(pair<int, int> i: plus_op) X.push_back(i.first); X.push_back(0); remove_dup(X); for(pair<int, int> i: subtract_op){ i.first = lower_bound(ALL(X), i.first) - X.begin(); packets[i.first].push_back(make_pair(i.second, -1)); } for(pair<int, int> i: plus_op){ i.first = lower_bound(ALL(X), i.first) - X.begin(); packets[i.first].push_back(make_pair(i.second, 1)); } pst.a.reserve(1e7); for(int i = 0; i < (int) X.size(); ++i){ for(pair<int, int> j: packets[i]){ pst.update(j.first, j.second); } version_at[i] = pst.get_cur_version(); } } int max_towers(int l, int r, int d) { l++; r++; int idx = upper_bound(ALL(X), d) - X.begin() - 1; int ans = pst.get(l, r, version_at[idx]); if (ans == 0){ pair<int, int> cur = st1.get(l, r); int mid = cur.second; if (mid > l){ int bruh = -st2.get(l, mid-1).first; if (cur.first - bruh >= d) ans++; } if (mid < r){ int bruh = -st2.get(mid+1, r).first; if (cur.first - bruh >= d) ans++; } maximize(ans, 1); } else{ int le = pst.walk_left(l, version_at[idx]); int ri = pst.walk_right(r, version_at[idx]); if (l < le){ pair<int, int> cur = st1.get(l, le - 1); if (cur.second > l){ int bruh = -st2.get(l, cur.second - 1).first; if (cur.first - max(bruh, a[le]) >= d) ans++; } } if (ri < r){ pair<int, int> cur = st1.get(ri+1, r); if (cur.second < r){ int bruh = -st2.get(cur.second+1, r).first; if (cur.first - max(bruh, a[ri]) >= d) ans++; } } } return ans; }
#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...