传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1558
【题解】
这题恶心死人了啊。。
网络上题解很多都是看代码看代码。。真是太不负责任了。。我这里详细说一下吧。。
题解在代码下面。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, a[M], b[M]; struct pa { int s, ll, rr, sz; // 连续(包括中间散的),左散,右散 long long l, r; pa() {} pa(int s, int ll, int rr, int sz, long long l, long long r) : s(s), ll(ll), rr(rr), sz(sz), l(l), r(r) {} friend pa operator + (pa a, pa b) { pa c; int f = (a.r == b.l); c.s = a.s + b.s; c.sz = a.sz + b.sz; c.l = a.l, c.r = b.r; if(a.s == 0 && b.s == 0) { if(!f) c.ll = c.rr = c.sz; else { c.ll = a.ll-1; c.rr = b.rr-1; ++c.s; } return c; } if(a.s == 0) { c.rr = b.rr; if(!f) c.ll = a.sz + b.ll; else { c.ll = a.ll-1; if(b.ll > 0) c.s += (b.ll-1)/2 + 1; } return c; } if(b.s == 0) { c.ll = a.ll; if(!f) c.rr = a.rr + b.sz; else { c.rr = b.rr-1; if(a.rr > 0) c.s += (a.rr-1)/2 + 1; } return c; } c.ll = a.ll, c.rr = b.rr; if(a.rr == 0 && b.ll == 0) { if(f) --c.s; return c; } if(a.rr == 0) { if(f) c.s += (b.ll-1)/2; else c.s += b.ll/2; return c; } if(b.ll == 0) { if(f) c.s += (a.rr-1)/2; else c.s += a.rr/2; return c; } int d = (a.rr + b.ll)/2; if(f) d = min(d, 1 + (a.rr-1)/2 + (b.ll-1)/2); c.s += d; return c; } }; namespace SMT { pa w[M]; ll tag[M]; # define ls (x<<1) # define rs (x<<1|1) inline void up(int x) { if(!x) return; if(!rs) {w[x] = w[ls]; return;} if(!ls) {w[x] = w[rs]; return;} w[x] = w[ls] + w[rs]; } inline void pushtag(int x, ll d) { w[x].l += d, w[x].r += d; tag[x] += d; } inline void down(int x) { if(!x) return; if(!tag[x]) return; pushtag(ls, tag[x]); pushtag(rs, tag[x]); tag[x] = 0; } inline void build(int x, int l, int r) { tag[x] = 0; if(l == r) { w[x] = pa(0, 1, 1, 1, b[l], b[l]); return ; } int mid = l+r>>1; build(ls, l, mid); build(rs, mid+1, r); up(x); } inline void edt(int x, int l, int r, int L, int R, ll d) { if(L <= l && r <= R) { pushtag(x, d); return ; } down(x); int mid = l+r>>1; if(L <= mid) edt(ls, l, mid, L, R, d); if(R > mid) edt(rs, mid+1, r, L, R, d); up(x); } inline pa query(int x, int l, int r, int L, int R) { if(L <= l && r <= R) return w[x]; down(x); int mid = l+r>>1; if(R <= mid) return query(ls, l, mid, L, R); else if(L > mid) return query(rs, mid+1, r, L, R); else return query(ls, l, mid, L, mid) + query(rs, mid+1, r, mid+1, R); } inline void debug(int x, int l, int r) { printf("x=%d, l=%d, r=%d: sum = %d, size = %d, left = %d, right = %d, lnum = %lld, rnum = %lld\n", x, l, r, w[x].s, w[x].sz, w[x].ll, w[x].rr, w[x].l, w[x].r); if(l==r) return; down(x); int mid = l+r>>1; debug(ls, l, mid); debug(rs, mid+1, r); } } int main() { int Q, l, r, a1, d; char opt[23]; pa t; cin >> n; for (int i=1; i<=n; ++i) scanf("%d", a+i); for (int i=1; i<n; ++i) b[i] = a[i+1] - a[i]; // for (int i=1; i<n; ++i) printf("%d ", b[i]); puts(""); cin >> Q; if(n == 1) { while(Q--) { scanf("%s", opt); if(opt[0] == 'A') scanf("%*d%*d%*d%*d"); if(opt[0] == 'B') {scanf("%*d%*d"); puts("1");} } return 0; } SMT::build(1, 1, n-1); // SMT::debug(1, 1, n-1); while(Q--) { scanf("%s", opt); if(opt[0] == 'A') { scanf("%d%d%d%d", &l, &r, &a1, &d); if(l != 1) SMT::edt(1, 1, n-1, l-1, l-1, a1); if(l <= r-1) SMT::edt(1, 1, n-1, l, r-1, d); if(r != n) SMT::edt(1, 1, n-1, r, r, -1ll * (r-l)*d - a1); } if(opt[0] == 'B') { scanf("%d%d", &l, &r); if(l == r) puts("1"); else { t = SMT::query(1, 1, n-1, l, r-1); int ans = (r-l+1+1)/2; if(t.s == 0) printf("%d\n", ans); else { ans = min(ans, t.s + (t.ll+1)/2 + (t.rr+1)/2); printf("%d\n", ans); } } } // SMT::debug(1, 1, n-1); } return 0; }