Codeforces 1136E Nastya Hasn't Written a Legend 线段树

vp的时候没码出来。。

我们用set去维护, 每一块区域, 每块区域内的元素与下一个元素的差值刚好为ki,每次加值的时候我们暴力合并,

可以发现我们最多合并O(n)次。 然后写个线段树就没了。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

int n, q, val[N], k[N];
LL prefix[N];
set<PII> seg;
char op[10];

LL a[N << 2], add[N << 2];
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
void push(int rt, int l, int mid, int r) {
    if(add[rt]) {
        a[rt << 1] += add[rt] * (mid - l + 1);
        a[rt << 1 | 1] += add[rt] * (r - mid);
        add[rt << 1] += add[rt];
        add[rt << 1 | 1] += add[rt];
        add[rt] = 0;
    }
}
void build(int l, int r, int rt) {
    if(l == r) {
        a[rt] = val[l];
        return;
    }
    int mid = l + r >> 1;
    build(lson); build(rson);
    a[rt] = a[rt << 1] + a[rt << 1 | 1];
}

void update(int L, int R, LL val, int l, int r, int rt) {
    if(l >= L && r <= R) {
        a[rt] += val * (r - l + 1);
        add[rt] += val;
        return;
    }
    int mid = l + r >> 1;
    push(rt, l, mid, r);
    if(L <= mid) update(L, R, val, lson);
    if(R > mid)  update(L, R, val, rson);
    a[rt] = a[rt << 1] + a[rt << 1 | 1];
}
LL query(int L, int R, int l, int r, int rt) {
    if(l >= L && r <= R) return a[rt];
    int mid = l + r >> 1;
    push(rt, l, mid, r);
    if(R <= mid) return query(L, R, lson);
    else if(L > mid) return query(L, R, rson);
    else return query(L, R, lson) + query(L, R, rson);
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &val[i]);
        prefix[i] = prefix[i - 1] + val[i];
    }
    for(int i = 1; i < n; i++) scanf("%d", &k[i]);
    for(int i = 1; i <= n; i++) seg.insert(mk(i, i));
    build(1, n, 1);
    scanf("%d", &q);
    while(q--) {
        scanf("%s", op);
        if(op[0] == '+') {
            int x, v; scanf("%d%d", &x, &v);
            auto sg = seg.upper_bound(mk(x, inf)); sg--;
            int L = sg->fi, R = sg->se;
            seg.erase(sg);
            if(L <= x - 1) seg.insert(mk(L, x - 1));
            update(x, R, v, 1, n, 1);
            while(R < n) {
                LL v1 = query(R, R, 1, n, 1);
                LL v2 = query(R + 1, R + 1, 1, n, 1);
                if(v1 + k[R] <= v2) break;
                LL add = v1 + k[R] - v2;
                auto sg = seg.lower_bound(mk(R + 1, R + 1));
                update(sg->fi, sg->se, add, 1, n, 1);
                R = sg->se;
                seg.erase(sg);
            }
            seg.insert(mk(x, R));
        } else {
            int L, R; scanf("%d%d", &L, &R);
            printf("%lld\n", query(L, R, 1, n, 1));
        }
    }
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10524045.html