Submission #569205

#TimeUsernameProblemLanguageResultExecution timeMemory
569205blueFish 2 (JOI22_fish2)C++17
100 / 100
1028 ms35728 KiB
#include <iostream> #include <vector> #include <algorithm> #include <cassert> using namespace std; using ll = long long; using vll = vector<ll>; using vvll = vector<vll>; using vi = vector<int>; using vvi = vector<vi>; using pii = pair<int, int>; using vpii = vector<pii>; #define sz(x) int(x.size()) int N; vll A; int Q; struct group { int i; //inclusive of the group, not the barrier. ll Asum; int winners; }; struct info { int l; int r; ll Asum; int winners; vector<group> pref; vector<group> suff; info() { ; } info(int i) { l = r = i; Asum = A[i]; winners = 1; } }; void combine(info& res, const info& X, const info& Y) //! { // cerr << "combine called\n"; res.l = X.l; res.r = Y.r; res.Asum = X.Asum + Y.Asum; res.winners = 0; int Xs = sz(X.suff); ll Xdp[1 + Xs]; Xdp[0] = A[X.r]; for(int i = 1; i <= Xs; i++) Xdp[i] = max(Xdp[i-1], A[X.suff[i-1].i - 1] - X.suff[i-1].Asum); int Ys = sz(Y.pref); ll Ydp[1 + Ys]; Ydp[0] = A[Y.l]; for(int i = 1; i <= Ys; i++) Ydp[i] = max(Ydp[i-1], A[Y.pref[i-1].i + 1] - Y.pref[i-1].Asum); // cerr << "#\n"; int XYreach[1 + Xs]; int XXreach[1 + Xs]; int YXreach[1 + Ys]; int YYreach[1 + Ys]; int xi, yi; yi = Ys; for(xi = Xs; xi >= 0; xi--) { ll currsum = (xi == Xs ? X.Asum : X.suff[xi].Asum); while(yi >= 0 && Ydp[yi] > currsum) yi--; ll Ygain; if(yi == Ys) Ygain = Y.Asum; else if(yi == -1) Ygain = 0; else Ygain = Y.pref[yi].Asum; if(xi < Xs && currsum + Ygain >= A[X.suff[xi].i - 1]) { XXreach[xi] = XXreach[xi+1]; XYreach[xi] = XYreach[xi+1]; } else { XXreach[xi] = xi; XYreach[xi] = yi; } } // cerr << "#2\n"; xi = Xs; for(yi = Ys; yi >= 0; yi--) { ll currsum = (yi == Ys ? Y.Asum : Y.pref[yi].Asum); while(xi >= 0 && Xdp[xi] > currsum) xi--; ll Xgain; if(xi == Xs) Xgain = X.Asum; else if(xi == -1) Xgain = 0; else Xgain = X.suff[xi].Asum; if(yi < Ys && currsum + Xgain >= A[Y.pref[yi].i + 1]) { YYreach[yi] = YYreach[yi+1]; YXreach[yi] = YXreach[yi+1]; } else { YYreach[yi] = yi; YXreach[yi] = xi; } } // cerr << "#3\n"; res.pref = X.pref; int pi = sz(res.pref); if(X.Asum < Ydp[0]) res.pref.push_back({X.r, X.Asum, 0}); for(int i = 0; i < sz(Y.pref); i++) if(A[Y.pref[i].i + 1] > Y.pref[i].Asum + X.Asum) res.pref.push_back({Y.pref[i].i, Y.pref[i].Asum + X.Asum, 0}); res.suff = Y.suff; int si = sz(res.suff); if(Y.Asum < Xdp[0]) res.suff.push_back({Y.l, Y.Asum, 0}); for(int i = 0; i < sz(X.suff); i++) if(A[X.suff[i].i - 1] > X.suff[i].Asum + Y.Asum) res.suff.push_back({X.suff[i].i, X.suff[i].Asum + Y.Asum, 0}); // cerr << "#4\n"; vpii newpref, newsuff; int pi2 = pi; int si2 = si; for(xi = 0; xi <= Xs; xi++) { int xiwinners = (xi == Xs ? X.winners : X.suff[xi].winners); if(XXreach[xi] == Xs && XYreach[xi] == Ys) res.winners += xiwinners; else if(XXreach[xi] == Xs) { // newpref.push_back({XYreach[xi], xiwinners}); int target = (XYreach[xi] == -1 ? X.r : Y.pref[XYreach[xi]].i); // // if(XYreach[xi] == -1) while(res.pref[pi2].i < target) pi2++; res.pref[pi2].winners += xiwinners; } else if(XYreach[xi] == Ys) { // newsuff.push_back({XXreach[xi], xiwinners}); int target = X.suff[XXreach[xi]].i; while(res.suff[si2].i > target) si2++; res.suff[si2].winners += xiwinners; } } pi2 = pi, si2 = si; // cerr << "#4-1\n"; for(yi = 0; yi <= Ys; yi++) { // cerr << "entered : " << yi << '\n'; int yiwinners = (yi == Ys ? Y.winners : Y.pref[yi].winners); if(YXreach[yi] == Xs && YYreach[yi] == Ys) res.winners += yiwinners; else if(YXreach[yi] == Xs) { // newpref.push_back({YYreach[yi], yiwinners}); int target = (YYreach[yi] == -1 ? X.r : Y.pref[YYreach[yi]].i); // // if(XYreach[xi] == -1) while(res.pref[pi2].i < target) pi2++; res.pref[pi2].winners += yiwinners; } else if(YYreach[yi] == Ys) { // newsuff.push_back({YXreach[yi], yiwinners}); int target = (YXreach[yi] == -1 ? Y.l : X.suff[YXreach[yi]].i); while(res.suff[si2].i > target) si2++; res.suff[si2].winners += yiwinners; } } // cerr << "#5\n"; // for(auto pr : newpref) // { // for(auto& respr : res.pref) // { // // assert(pr.first < sz(Y.pref)); // if(pr.first == -1 && respr.i == X.r) // respr.winners += pr.second; // else if(pr.first != -1 && respr.i == Y.pref[pr.first].i) // respr.winners += pr.second; // } // } // // cerr << "hello\n"; // for(auto sf : newsuff) // { // // cerr << sf.first << ' ' << sf.second << '\n'; // for(auto& ressf : res.suff) // { // assert(sf.first < sz(X.suff)); // // cerr << " " << ressf.i << ' ' << ressf.Asum << ' ' << ressf.winners << '\n'; // // cerr << "sff = " << sf.first << '\n'; // // cerr << X.suff[sf.first.i] << '\n'; // if(sf.first == -1 && ressf.i == Y.l) // { // // cerr << "bye\n"; // ressf.winners += sf.second; // // cerr << "bye done\n"; // } // else if(sf.first != -1 && ressf.i == X.suff[sf.first].i) // { // // cerr << "bye2\n"; // ressf.winners += sf.second; // } // } // } // Y = info(1); // return res; // cerr << "combine end\n"; } info combine(const info& A, const info& B) { info res; combine(res, A, B); return res; } struct segtree { info v; segtree* left = NULL; segtree* right = NULL; segtree() { ; } segtree(int L, int R) { if(L == R) v = info(L); else { left = new segtree(L, (L+R)/2); right = new segtree((L+R)/2+1, R); combine(v, left->v, right->v); } } void recompute(int I) { // cerr << "recompute : " << v.l << ' ' << v.r << ' ' << I << '\n'; if(v.l == v.r) v = info(v.l); else { if(I <= (v.l+v.r)/2) left->recompute(I); else right->recompute(I); // cerr << "###\n"; combine(v, left->v, right->v); // cerr << "combine done\n"; } // cerr << "done\n"; } info range(int L, int R) { if(L <= v.l && v.r <= R) return v; else if(R <= (v.l+v.r)/2) return left->range(L, R); else if(L >= (v.l+v.r)/2+1) return right->range(L, R); else return combine(left->range(L, R), right->range(L, R)); } }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> N; A = vll(1+N); for(int i = 1; i <= N; i++) cin >> A[i]; // cerr << "done\n"; segtree S(1, N); // cerr << "done2\n"; cin >> Q; for(int j = 1; j <= Q; j++) { int T; cin >> T; if(T == 1) { int X, Y; cin >> X >> Y; A[X] = Y; S.recompute(X); // cerr << "hello\n"; } else { int L, R; cin >> L >> R; cout << S.range(L, R).winners << '\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...