Submission #625965

#TimeUsernameProblemLanguageResultExecution timeMemory
625965jtnydv25Radio Towers (IOI22_towers)C++17
100 / 100
1725 ms325676 KiB
// #pragma once #include <bits/stdc++.h> using namespace std; #define ll long long #define pii pair<int, int> #define all(c) ((c).begin()), ((c).end()) #define sz(x) ((int)(x).size()) #ifdef LOCAL #include <print.h> #else #define trace(...) #define endl "\n" // remove in interactive #endif const int MAX = 1000000000; const int LOG = 18; struct Node{ Node* lft, *rgt; int sum; Node(){lft = rgt = NULL; sum = 0;} }; Node* add(Node* rt, int x, int s = 0, int e = MAX){ Node* rt2 = new Node(); Node* ret = rt2; while(true){ rt2->sum = (rt ? rt->sum: 0) + 1; if(s == e) break; int mid = (s + e) / 2; if(x <= mid){ rt2->rgt = rt ? rt->rgt: NULL; rt2->lft = new Node(); rt2 = rt2->lft; if(rt) rt = rt->lft; e = mid; } else{ rt2->lft = rt ? rt->lft: NULL; rt2->rgt = new Node(); rt2 = rt2->rgt; if(rt) rt = rt->rgt; s = mid + 1; } } return ret; } int getNum(Node* rt, int L, int R, int s = 0, int e = MAX){ if(!rt) return 0; if(L > e || R < s) return 0; if(s >= L && e <= R) return rt->sum; int mid = (s + e) >> 1; return getNum(rt->lft, L, R, s, mid) + getNum(rt->rgt, L, R, mid + 1, e); } // 0-indexed template<class T> struct sparse_table{ vector<vector<T>> arr; vector<int> floorlog; function<T(T, T)> func; int n; sparse_table(){} sparse_table(vector<T> & vec, function<T(T, T)> f) : n(sz(vec)), floorlog(sz(vec) + 1), func(f){ for(int i = 0; (1 << i) <= n; i++){ for(int j = (1 << i); j < (1 << (i + 1)) && j <= n; j++) floorlog[j] = i; } arr.assign(floorlog[n] + 1, vector<T>(n)); for(int i = n - 1; i >= 0; i--){ arr[0][i] = vec[i]; for(int j = 1; i + (1 << j) <= n; j++){ arr[j][i] = func(arr[j - 1][i], arr[j - 1][i + (1 << (j - 1))]); } } } T get(int i, int j){ int k = floorlog[j - i + 1]; return func(arr[k][i], arr[k][j - (1 << k) + 1]); } }; struct Tree{ int n; vector<Node*> root_seg; vector<vector<int>> jump; vector<int> par; Tree(){} Tree(int n): n(n), par(n+1), root_seg(n+1, NULL){} void get_jumps(){ root_seg[n] = new Node(); jump.resize(LOG); par[n] = n; jump[0] = par; for(int i = 0; i < n; i++) if(jump[0][i] == -1) jump[0][i] = n; jump[0][n] = n; for(int j = 1; j < LOG; j++){ jump[j].resize(n + 1); for(int i = 0; i <= n; i++) jump[j][i] = jump[j - 1][jump[j - 1][i]]; } } }; // global variables vector<int> H, V; sparse_table<int> st, st_ind; Tree TL, TR, T0; int n; int getMin(int L, int R){ if(L > R)swap(L, R); return st.get(L, R); } void init(int N, std::vector<int> HH){ H = HH; H.push_back(MAX+10); n = N; vector<int> ids(n); iota(ids.begin(), ids.end(), 0); st = sparse_table<int>(H, [](int i, int j){return min(i, j);}); st_ind = sparse_table<int>(ids, [](int i, int j){return H[i] > H[j] ? i : j;}); TL = Tree(n); TR = Tree(n); T0 = Tree(n); stack<int> stk; Node* zero = new Node(); for(int i = 0; i < n; i++){ while(!stk.empty() && H[stk.top()] < H[i]) stk.pop(); TL.par[i] = stk.empty() ? -1: stk.top(); stk.push(i); } while(!stk.empty()) stk.pop(); for(int i = n - 1; i >= 0; i--){ while(!stk.empty() && H[stk.top()] < H[i]) stk.pop(); TR.par[i] = stk.empty() ? n: stk.top(); stk.push(i); } V.resize(n); for(int i = 0; i < n; i++){ int L = TL.par[i], R = TR.par[i]; int mn = max(getMin(L + 1, i), getMin(i, R - 1)); int D_max = max(0, H[i] - mn); V[i] = D_max; T0.root_seg[i] = add(i == 0 ? zero: T0.root_seg[i - 1], D_max); TL.root_seg[i] = add(TL.par[i] == -1 ? zero: TL.root_seg[TL.par[i]], D_max); } for(int i = n - 1; i >= 0; i--){ TR.root_seg[i] = add(TR.par[i] == n ? zero: TR.root_seg[TR.par[i]], V[i]); } TL.get_jumps(); TR.get_jumps(); } int fix_seq(const Tree& T, int mx_H, int i, int D){ // sequence i -> par[i] -> .. till height < mx_H // subtract for those j in this sequence where getMin(i, j) > H[j] - D if(H[i] >= mx_H) return 0; int j = i; for(int k = LOG - 1; k >= 0; k--){ int p = T.jump[k][j]; if(H[p] < mx_H && getMin(i, p) > H[p] - D) j = p; } j = T.jump[0][j]; return getNum(T.root_seg[i], D, MAX) - getNum(T.root_seg[j], D, MAX); } int max_towers(int L, int R, int D){ int ret = 1 + getNum(T0.root_seg[R], D, MAX) - (L == 0 ? 0: getNum(T0.root_seg[L - 1], D, MAX)); int mx = st_ind.get(L, R); ret -= V[mx] >= D; ret += H[mx] - max(getMin(L, mx), getMin(mx, R)) >= D; ret -= fix_seq(TR, H[mx], L, D); ret -= fix_seq(TL, H[mx], R, D); return ret; }

Compilation message (stderr)

towers.cpp: In constructor 'Tree::Tree(int)':
towers.cpp:91:17: warning: 'Tree::par' will be initialized after [-Wreorder]
   91 |     vector<int> par;
      |                 ^~~
towers.cpp:89:19: warning:   'std::vector<Node*> Tree::root_seg' [-Wreorder]
   89 |     vector<Node*> root_seg;
      |                   ^~~~~~~~
towers.cpp:93:5: warning:   when initialized here [-Wreorder]
   93 |     Tree(int n): n(n), par(n+1), root_seg(n+1, NULL){}
      |     ^~~~
towers.cpp: In instantiation of 'sparse_table<T>::sparse_table(std::vector<_Tp>&, std::function<T(T, T)>) [with T = int]':
towers.cpp:124:66:   required from here
towers.cpp:64:9: warning: 'sparse_table<int>::n' will be initialized after [-Wreorder]
   64 |     int n;
      |         ^
towers.cpp:62:17: warning:   'std::vector<int> sparse_table<int>::floorlog' [-Wreorder]
   62 |     vector<int> floorlog;
      |                 ^~~~~~~~
towers.cpp:66:5: warning:   when initialized here [-Wreorder]
   66 |     sparse_table(vector<T> & vec, function<T(T, T)> f) : n(sz(vec)), floorlog(sz(vec) + 1), func(f){
      |     ^~~~~~~~~~~~
#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...