[COGS2651]新史「新幻想史 -现代史-」

题目链接COGS2651

题目大意
作为知识与历史的半兽,慧音可以更改某个时刻的历史: t 时刻及以后,区间[l1..r1]的妖怪能力减弱 x1 ,同时区间 [l2..r2] 的妖怪能力增强 x2
这里写图片描述
询问和修改交错给出,问慧音在进行了前面的操作后,时刻 t [l..r]的妖怪的能力和。

分析
1. 我们把妖怪在所有时刻的状态平铺在平面上,初始化全部为初始状态:比如

时刻1时刻2时刻3时刻4
妖怪11111
妖怪22222
妖怪33333
妖怪44444

2. 然后,修改操作就变成了修改平面上一个矩形的值,比如:
进行操作M 4 4 5 1 2 1 3

时刻1时刻2时刻3时刻4
妖怪11122
妖怪22233
妖怪33333
妖怪444-1-1

3. 于是就与另一道经典CDQ分治十分相似了:Mokia题解,只不过是把单点修改变成了区间修改,而且修改不用拆分成前后两段,因为这道题的询问只有左界没有右界。
ps. COGS也有Mokia这道题。
UPD: 换了一份代码。

上代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N = 5e4 + 10;
const int M = 1e5 + 10;

int n, m, t;
inline int read() {
    register char ch = getchar();
    register int ans = 0, neg = 1;
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-') neg = -1;
    for (; isdigit(ch); ch = getchar())
        ans = ans * 10 + ch - '0';
    return ans * neg;
}


namespace ST {
    const int M = 3e5 + 10;

    bool cls[M];
    LL val[M], add[M];
    #define lc(a) (a << 1)
    #define rc(a) (lc(a) | 1)
    inline void clearVal(int a) {
        cls[a] = true, val[a] = add[a] = 0;
    }
    inline void addVal(int a, int l, int r, int c) {
        add[a] += c, val[a] += (LL)c * (r - l + 1);
    }
    inline void pushDown(int a, int l, int r) {
        if (cls[a]) {
            cls[a] = false;
            clearVal(lc(a)), clearVal(rc(a));
        }
        if (add[a]) {
            int mid = (l + r) >> 1;
            addVal(lc(a), l, mid, add[a]);
            addVal(rc(a), mid + 1, r, add[a]);
            add[a] = 0;
        }
    }
    void build(int a, int l, int r) {
        if (l == r) return val[a] = read(), void(0);
        int mid = (l + r) >> 1;
        build(lc(a), l, mid), build(rc(a), mid + 1, r);
        val[a] = val[lc(a)] + val[rc(a)];
    }
    void modify(int a, int l, int r, int ll, int rr, int c) {
        pushDown(a, l, r);
        if (l == ll && r == rr) return addVal(a, l, r, c);
        val[a] += (LL)c * (rr - ll + 1);
        int mid = (l + r) >> 1;
        if (rr <= mid) return modify(lc(a), l, mid, ll, rr, c);
        else if (ll > mid) return modify(rc(a), mid + 1, r, ll, rr, c);
        return modify(lc(a), l, mid, ll, mid, c), modify(rc(a), mid + 1, r, mid + 1, rr, c);
    }
    LL query(int a, int l, int r, int ll, int rr) {
        pushDown(a, l, r);
        if (l == ll && r == rr) return val[a];
        int mid = (l + r) >> 1;
        if (rr <= mid) return query(lc(a), l, mid, ll, rr);
        else if (ll > mid) return query(rc(a), mid + 1, r, ll, rr);
        return query(lc(a), l, mid, ll, mid) + query(rc(a), mid + 1, r, mid + 1, rr);
    }
}

int cnt, cntAns;
LL ans[N];
struct Op {
    int type, l, r, t, c;
    LL *plc;
} op[M];

void init() {
    n = read(), m = read();
    ST::build(1, 1, n);
    char ss[5];
    for (int i = 1; i <= m; ++i)
        if (scanf("%s", ss), *ss == 'Q') {
            op[++cnt].type = 0;
            op[cnt].l = read(), op[cnt].r = read(), op[cnt].t = read();
            op[cnt].plc = &ans[++cntAns];
            ans[cntAns] += ST::query(1, 1, n, op[cnt].l, op[cnt].r);
        } else {
            op[++cnt].type = 1;
            op[cnt].l = read(), op[cnt].r = read(), op[cnt].c = -read();
            op[++cnt].type = 1;
            op[cnt].l = read(), op[cnt].r = read(), op[cnt].c = read();
            op[cnt - 1].t = op[cnt].t = read();
        }
}

Op ary[M];
void figure(int l, int r) {
    if (l == r) return;
    int mid = (l + r) >> 1;
    figure(l, mid), figure(mid + 1, r);
    ST::clearVal(1);
    int ll = l, rr = mid + 1, tmp = l - 1;
    while (ll <= mid && rr <= r) {
        if (op[ll].t <= op[rr].t) {
            ary[++tmp] = op[ll++];
            if (ary[tmp].type)
                ST::modify(1, 1, n, ary[tmp].l, ary[tmp].r, ary[tmp].c);
        } else {
            ary[++tmp] = op[rr++];
            if (!ary[tmp].type)
                *ary[tmp].plc += ST::query(1, 1, n, ary[tmp].l, ary[tmp].r);
        }
    }
    while (ll <= mid) {
        ary[++tmp] = op[ll++];
        if (ary[tmp].type)
            ST::modify(1, 1, n, ary[tmp].l, ary[tmp].r, ary[tmp].c);
    }
    while (rr <= r) {
        ary[++tmp] = op[rr++];
        if (!ary[tmp].type)
            *ary[tmp].plc += ST::query(1, 1, n, ary[tmp].l, ary[tmp].r);
    }
    for (int i = l; i <= r; ++i) op[i] = ary[i];
}

int main() {
//  freopen("cdcq_a.in", "r", stdin);
//  freopen("cdcq_a.out", "w", stdout);
    init();
    figure(1, cnt);
    for (int i = 1; i <= cntAns; ++i)
        printf("%lld\n", ans[i]);
    return 0;
}

以上

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值