Submission #572066

#TimeUsernameProblemLanguageResultExecution timeMemory
572066gs14004Fish 2 (JOI22_fish2)C++17
100 / 100
3566 ms34020 KiB
#include <bits/stdc++.h> #define sz(v) ((int)(v).size()) #define all(v) (v).begin(), (v).end() using namespace std; typedef long long lint; typedef pair<lint, lint> pi; const int MAXN = 100005; const int MAXT = 270000; lint a[MAXN]; struct node{ int s, e, cost; bool operator<(const node &nd)const{ return pi(s, -e) < pi(nd.s, -nd.e); } bool operator==(const node &nd)const{ return pi(s, -e) == pi(nd.s, -nd.e); } }; struct bit{ lint tree[MAXN]; void add(int x, lint v){ for(int i = x; i < MAXN; i += i & -i) tree[i] += v; } lint query(int x){ lint ret = 0; for(int i = x; i; i -= i & -i) ret += tree[i]; return ret; } lint query(int s, int e){ if(s > e) return 0; return query(e) - query(s - 1); } }bit, subs; struct seg{ lint tree[MAXT]; void init(int s, int e, int p, lint *a){ if(s == e){ tree[p] = a[s]; return; } int m = (s+e)/2; init(s, m, 2*p, a); init(m+1, e, 2*p+1, a); tree[p] = max(tree[2*p], tree[2*p+1]); } void upd(int pos, int s, int e, int p, lint v){ if(s == e){ tree[p] = v; return; } int m = (s + e) / 2; if(pos <= m) upd(pos, s, m, 2*p, v); else upd(pos, m+1, e, 2*p+1, v); tree[p] = max(tree[2*p], tree[2*p+1]); } int queryLeft(int s, int e, int ps, int pe, int p, lint v){ if(e < ps || pe < s) return 1e9; if(tree[p] <= v) return 1e9; if(ps == pe) return ps; int pm = (ps + pe) / 2; if(s <= ps && pe <= e){ if(tree[2*p] > v) return queryLeft(s, e, ps, pm, 2*p, v); return queryLeft(s, e, pm+1, pe, 2*p+1, v); } int r = queryLeft(s, e, ps, pm, 2*p, v); if(r < 1e7) return r; return queryLeft(s, e, pm+1, pe, 2*p+1, v); } int queryRight(int s, int e, int ps, int pe, int p, lint v){ if(e < ps || pe < s) return -1e9; if(tree[p] <= v) return -1e9; if(ps == pe) return ps; int pm = (ps + pe) / 2; if(s <= ps && pe <= e){ if(tree[2*p+1] > v) return queryRight(s, e, pm+1, pe, 2*p+1, v); return queryRight(s, e, ps, pm, 2*p, v); } int r = queryRight(s, e, pm+1, pe, 2*p+1, v); if(r > 0) return r; return queryRight(s, e, ps, pm, 2*p, v); } }seg; int n; set<node> st; void getNodeSet(int x, vector<node> &v){ if(x < 2 || x >= n) return; int l = x, r = x; while(true){ lint curSum = bit.query(l, r); if(curSum < min(a[l-1], a[r+1])){ v.push_back({l, r, -1}); if(l == 2 && r == n - 1) break; if(a[l-1] < a[r+1]) l--; else r++; } curSum = bit.query(l, r); int leftClosest = seg.queryRight(1, l - 1, 1, n, 1, curSum); int rightClosest = seg.queryLeft(r + 1, n, 1, n, 1, curSum); l = leftClosest + 1; r = rightClosest - 1; } } void add(int x, int v){ vector<node> l; getNodeSet(x-1, l); getNodeSet(x, l); getNodeSet(x+1, l); sort(all(l)); reverse(all(l)); l.resize(unique(all(l)) - l.begin()); for(auto &x : l){ auto it = st.lower_bound({x.s, x.e, -1}); if(it != st.end() && it->s == x.s && it->e == x.e){ // cout << "erase interval " << x.s << " " << x.e << " " << it->cost << endl; subs.add(it->s - 1, -it->cost); st.erase(it); } else assert(0); } l.clear(); bit.add(x, v); a[x] += v; seg.upd(x, 1, n, 1, a[x]); getNodeSet(x-1, l); getNodeSet(x, l); getNodeSet(x+1, l); sort(all(l)); reverse(all(l)); l.resize(unique(all(l)) - l.begin()); for(auto &x : l){ auto it = st.lower_bound({x.s, x.e, -1}); if(it != st.end() && it->s == x.s && it->e == x.e){ assert(0); } int sum = subs.query(x.s - 1, x.e); subs.add(x.s - 1, x.e - x.s + 1 - sum); st.insert({x.s, x.e, x.e - x.s + 1 - sum}); // cout << "Add interval " << x.s << " " << x.e << " " << x.e - x.s + 1 - sum << endl; } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; a[1] = a[n + 2] = 1e15; for(int i = 2; i <= n + 1; i++){ cin >> a[i]; } n += 2; seg.init(1, n, 1, a); for(int i = 1; i <= n; i++){ bit.add(i, a[i]); } vector<node> l; for(int i = 2; i <= n - 1; i++){ getNodeSet(i, l); } sort(all(l)); reverse(all(l)); l.resize(unique(all(l)) - l.begin()); for(auto &x : l){ auto it = st.lower_bound({x.s, x.e, -1}); if(it != st.end() && it->s == x.s && it->e == x.e){ assert(0); } int sum = subs.query(x.s - 1, x.e); subs.add(x.s - 1, x.e - x.s + 1 - sum); st.insert({x.s, x.e, x.e - x.s + 1 - sum}); // cout << "Add interval " << x.s << " " << x.e << " " << x.e - x.s + 1 - sum << endl; } int q; cin >> q; while(q--){ int t, x, y; cin >> t >> x >> y; if(t == 1){ x++; add(x, y - a[x]); } else{ x++; y++; int sx = x, sy = y; for(int i = x; i < y; ){ int j = seg.queryLeft(i + 1, y, 1, n, 1, bit.query(x, i)); if(j > 1e8) break; if(bit.query(x, j - 1) < a[j]) sx = j; i = j; } for(int i = y; i > x; ){ int j = seg.queryRight(x, i - 1, 1, n, 1, bit.query(i, y)); if(j < 0) break; if(bit.query(j + 1, y) < a[j]) sy = j; i = j; } cout << sy - sx + 1 - subs.query(sx, sy - 1) << "\n"; } } }
#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...