Submission #1256445

#TimeUsernameProblemLanguageResultExecution timeMemory
1256445Zbyszek99Tortoise (CEOI21_tortoise)C++20
100 / 100
1632 ms72068 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define ll long long #define ld long double #define ull unsigned long long #define ff first #define ss second #define pii pair<int,int> #define pll pair<long long, long long> #define vi vector<int> #define vl vector<long long> #define pb push_back #define rep(i, b) for(int i = 0; i < (b); ++i) #define rep2(i,a,b) for(int i = a; i <= (b); ++i) #define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c) #define count_bits(x) __builtin_popcountll((x)) #define all(x) (x).begin(),(x).end() #define siz(x) (int)(x).size() #define forall(it,x) for(auto& it:(x)) using namespace __gnu_pbds; using namespace std; typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set; //mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());} //ll los(ll a, ll b) {return a + (mt() % (b-a+1));} const int INF = 1e9+50; const ll INF_L = 1e18+40; const ll MOD = 1e9+7; const int maxn = 500001; int dist[maxn]; int seg_ind[maxn]; bool was_del[maxn]; set<int> not_take[maxn]; int take[maxn]; const int tree_siz = 1024*1024-1; int min_[tree_siz+1]; int oper[tree_siz+1]; void spych(int v) { min_[v*2] += oper[v]; min_[v*2+1] += oper[v]; oper[v*2] += oper[v]; oper[v*2+1] += oper[v]; oper[v] = 0; } int get_seg(int akt, int p1, int p2, int s1, int s2) { if(p2 < s1 || p1 > s2) return 1e9; if(p1 >= s1 && p2 <= s2) { return min_[akt]; } spych(akt); return min(get_seg(akt*2,p1,(p1+p2)/2,s1,s2),get_seg(akt*2+1,(p1+p2)/2+1,p2,s1,s2)); } void change_min(int akt, int p1, int p2, int s1, int s2, int w) { if(s1 > s2) return; if(p2 < s1 || p1 > s2) return; if(p1 >= s1 && p2 <= s2) { oper[akt] += w; min_[akt] += w; return; } spych(akt); change_min(akt*2,p1,(p1+p2)/2,s1,s2,w); change_min(akt*2+1,(p1+p2)/2+1,p2,s1,s2,w); min_[akt] = min(min_[akt*2],min_[akt*2+1]); } int n; int c_left[maxn]; int c_right[maxn]; void add_left(int v, int k) { if(k == 0) return; c_left[v] += k; take[v] += k; change_min(1,0,tree_siz/2,v+1,n,-dist[v]*k*2); int d = 1; if(k < 0) d = -1; change_min(1,0,tree_siz/2,v,v,-dist[v]*2*(k-d)); } void add_right(int v, int k) { if(k == 0) return; c_right[v] += k; take[v] += k; change_min(1,0,tree_siz/2,v+1,n,-dist[v]*k*2); change_min(1,0,tree_siz/2,v,v,-dist[v]*(2*k)); } bool valid() { return get_seg(1,0,tree_siz/2,0,n-1) >= 0; } int main() { //ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); //random_start(); cin >> n; ll sum = 0; ll ans = 0; vl arr(n); rep(i,n) cin >> arr[i]; rep(i,n) if(arr[i] != -1) sum += arr[i]; int pop = -1e7; rep(i,n) dist[i] = 1e7; rep(i,n) { if(arr[i] == -1) pop = i; else dist[i] = min(dist[i],i-pop); } pop = 1e7; for(int i = n-1; i >= 0; i--) { if(arr[i] == -1) pop = i; else { dist[i] = min(dist[i],pop-i); } } rep(i,n+1) change_min(1,0,tree_siz/2,i,i,1e7+i); vector<pii> segs; int start = 0; rep(i,n) { if(arr[i] == -1) { if(start != i) { segs.pb({start,i-1}); } start = i+1; } } if(start != n) segs.pb({start,n-1}); rep(i,siz(segs)) { rep2(j,segs[i].ff,segs[i].ss) { if(arr[j] != 0) not_take[i].insert(j); seg_ind[j] = i; } if(siz(not_take[i]) != 0 && segs[i].ss != n-1) { int nt = *(--not_take[i].end()); change_min(1,0,tree_siz/2,nt,nt,-1e7); ans++; } } vector<pii> v_sort; rep(i,n) { if(arr[i] > 0) { v_sort.pb({dist[i],i}); } } sort(all(v_sort)); forall(it,v_sort) { int v = it.ss; int s = seg_ind[v]; int mid = (segs[s].ff+segs[s].ss+1)/2; if(segs[s].ss == n-1) mid = n; if(segs[s].ff == 0) mid = -1; int k = 0; if(v < mid) { //left rep2(i,1,arr[v]) { add_left(v,i); bool is = 1; int nt = *(--not_take[s].end()); if(mid != n) { if(nt == v) { if(i == arr[v]) { not_take[s].erase(v); is = 0; } else { change_min(1,0,tree_siz/2,v,v,-dist[v]*2); } } else { if(arr[v] == i) not_take[s].erase(v); change_min(1,0,tree_siz/2,v,v,-1e7); } } else { change_min(1,0,tree_siz/2,v,v,-1e7); } is = is && valid(); add_left(v,-i); if(mid != n) { if(nt == v) { if(i == arr[v]) { is = 0; not_take[s].insert(v); } else { change_min(1,0,tree_siz/2,v,v,dist[v]*2); } } else { if(arr[v] == i) not_take[s].insert(v); change_min(1,0,tree_siz/2,v,v,1e7); } } else { change_min(1,0,tree_siz/2,v,v,1e7); } if(!is) break; k++; ans++; } if(k != 0) { add_left(v,k); int nt = *(--not_take[s].end()); if(mid != n) { if(nt == v) { change_min(1,0,tree_siz/2,v,v,-dist[v]*2); } else { if(k == arr[v]) not_take[s].erase(v); change_min(1,0,tree_siz/2,v,v,-1e7); } } else { change_min(1,0,tree_siz/2,v,v,-1e7); } } } else { //right rep2(i,1,arr[v]) { add_right(v,i); bool is = 1; int nt = *(--not_take[s].end()); if(nt == v) { if(i == arr[v]) { not_take[s].erase(v); if(siz(not_take[s]) == 0) is = 0; else { int nt2 = *(--not_take[s].end()); if(take[nt2] == 0) change_min(1,0,tree_siz/2,nt2,nt2,-1e7); if(nt2 < mid && take[nt2] > 0) change_min(1,0,tree_siz/2,nt2,nt2,-dist[nt2]); } } } else { if(i == arr[v]) not_take[s].erase(v); change_min(1,0,tree_siz/2,v,v,-1e7); } is = is && valid(); add_right(v,-i); if(nt == v) { if(i == arr[v]) { if(siz(not_take[s]) == 0) is = 0; else { int nt2 = *(--not_take[s].end()); if(take[nt2] == 0) change_min(1,0,tree_siz/2,nt2,nt2,1e7); if(nt2 < mid && take[nt2] > 0) change_min(1,0,tree_siz/2,nt2,nt2,dist[nt2]); } not_take[s].insert(v); } } else { if(i == arr[v]) not_take[s].insert(v); change_min(1,0,tree_siz/2,v,v,1e7); } if(!is) break; k++; ans++; } if(k != 0) { add_right(v,k); int nt = *(--not_take[s].end()); if(nt == v) { if(k == arr[v]) { not_take[s].erase(v); int nt2 = *(--not_take[s].end()); if(take[nt2] == 0) change_min(1,0,tree_siz/2,nt2,nt2,-1e7); if(nt2 < mid && take[nt2] > 0) change_min(1,0,tree_siz/2,nt2,nt2,-dist[nt2]); } } else { if(k == arr[v]) not_take[s].erase(v); change_min(1,0,tree_siz/2,v,v,-1e7); } } } } cout << sum-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...