传送门: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;
}
View Code

相关文章: