Submission #1046626

#TimeUsernameProblemLanguageResultExecution timeMemory
1046626juicyFish 2 (JOI22_fish2)C++17
100 / 100
1974 ms9576 KiB
// https://oj.uz/submission/937840 // https://codeforces.com/blog/entry/101003?#comment-898608 // https://www2.ioi-jp.org/camp/2022/2022-sp-tasks/contest4/fish2-review.pdf #include <bits/stdc++.h> using namespace std; #ifdef LOCAL #include "debug.h" #else #define debug(...) 42 #endif const int N = 1e5 + 5, inf = 1e9 + 7; int n, q; int a[N], ma[4 * N], lz[4 * N]; array<int, 2> s[4 * N]; array<int, 2> operator + (const array<int, 2> &lt, const array<int, 2> &rt) { array<int, 2> res{}; res[0] = min(lt[0], rt[0]); if (res[0] == lt[0]) { res[1] += lt[1]; } if (res[0] == rt[0]) { res[1] += rt[1]; } return res; } namespace ft { long long ft[N]; void upd(int i, int x) { for (; i <= n; i += i & -i) { ft[i] += x; } } long long qry(int i) { long long res = 0; for (; i; i -= i & -i) { res += ft[i]; } return res; } long long qry(int l, int r) { return qry(r) - qry(l - 1); } } void upd(int i, int x, int id = 1, int l = 1, int r = n) { if (l == r) { ma[id] = x; return; } int md = (l + r) / 2; if (i <= md) { upd(i, x, id * 2, l, md); } else { upd(i, x, id * 2 + 1, md + 1, r); } ma[id] = max(ma[id * 2], ma[id * 2 + 1]); } int walklt(int i, long long k, int id = 1, int l = 1, int r = n) { if (l >= i || ma[id] <= k) { return 0; } if (l == r) { return l; } int md = (l + r) / 2; auto res = walklt(i, k, id * 2 + 1, md + 1, r); return res == 0 ? walklt(i, k, id * 2, l, md) : res; } int walkrt(int i, long long k, int id = 1, int l = 1, int r = n) { if (r <= i || ma[id] <= k) { return n + 1; } if (l == r) { return l; } int md = (l + r) / 2; auto res = walkrt(i, k, id * 2, l, md); return res == n + 1 ? walkrt(i, k, id * 2 + 1, md + 1, r) : res; } void app(int id, int x) { s[id][0] += x; lz[id] += x; } void psh(int id) { if (lz[id]) { app(id * 2, lz[id]); app(id * 2 + 1, lz[id]); lz[id] = 0; } } void bld(int id = 1, int l = 1, int r = n) { if (l == r) { s[id] = {0, 1}; return; } int md = (l + r) / 2; bld(id * 2, l, md); bld(id * 2 + 1, md + 1, r); s[id] = s[id * 2] + s[id * 2 + 1]; } void add(int u, int v, int x, int id = 1, int l = 1, int r = n) { if (u <= l && r <= v) { app(id, x); return; } psh(id); int md = (l + r) / 2; if (u <= md) { add(u, v, x, id * 2, l, md); } if (md < v) { add(u, v, x, id * 2 + 1, md + 1, r); } s[id] = s[id * 2] + s[id * 2 + 1]; } array<int, 2> get(int u, int v, int id = 1, int l = 1, int r = n) { if (u <= l && r <= v) { return s[id]; } psh(id); int md = (l + r) / 2; if (v <= md) { return get(u, v, id * 2, l, md); } if (md < u) { return get(u, v, id * 2 + 1, md + 1, r); } return get(u, v, id * 2, l, md) + get(u, v, id * 2 + 1, md + 1, r); } bool check(int l, int r, long long &sum) { sum = ft::qry(l + 1, r - 1); return sum < min(a[l], a[r]); } vector<array<int, 2>> getcands(int p) { if (p == 0 || p == n + 1) { return {}; } int l = p, r = p; long long cur = a[p]; vector<array<int, 2>> cands; while (1) { int s = walklt(l, cur), e = walkrt(r, cur); if (s == 0 && e == n + 1) { break; } if (check(s, e, cur)) { cands.push_back({s + 1, e - 1}); } if (a[s] <= a[e]) { l = s; } else { r = e; } } return cands; } void up(int i, int x) { auto cands = getcands(i); auto lt = getcands(i - 1); auto rt = getcands(i + 1); for (auto [l, r] : cands) { add(l, r, x); } for (auto [l, r] : lt) { if (r == i - 1) { add(l, r, x); } } for (auto [l, r] : rt) { if (l == i + 1) { add(l, r, x); } } } void chg(int i, int x) { up(i, -1); ft::upd(i, x - a[i]); a[i] = x; upd(i, x); up(i, 1); } int findlt(int l, int r) { int res = l, p = l; long long cur = a[l]; while (1) { p = walkrt(p, cur); if (p > r) { break; } cur = ft::qry(l, p - 1); if (cur < a[p]) { res = p; } } return res; } int findrt(int l, int r) { int res = r, p = r; long long cur = a[r]; while (1) { p = walklt(p, cur); if (p < l) { break; } cur = ft::qry(p + 1, r); if (cur < a[p]) { res = p; } } return res; } int qry(int l, int r) { int s = findlt(l, r), e = findrt(l, r); if (s > e) { return 0; } return get(s, e)[1]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; bld(); a[0] = a[n + 1] = inf; for (int i = 1; i <= n; ++i) { int x; cin >> x; chg(i, x); } cin >> q; while (q--) { int t; cin >> t; if (t == 1) { int x, y; cin >> x >> y; chg(x, y); } else { int s, e; cin >> s >> e; cout << qry(s, e) << "\n"; } } return 0; } // an interesting observation that I haven't taken advantage of // A >= sum(x - 1) - sum(l - 1) // -> A - sum(x - 1) >= -sum(l - 1) (can be solved with lazy segtree)
#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...