Luogu4231 三步必杀

跟前两天考试题挺像的,就直接说做法了

其实就是你发现在各种数据结构都不是很资瓷之后,你选择了差分

发现差分之后每次操作就变成了对差分序列做区间覆盖

可以 log 做,但显然 mlogn 在 0.5s 之内是会非常爆炸的

可能因为上边想到想到差分序列的性质之后太兴奋了

实际上标准的区间加也是可以差分的啊!

这样再差分一次就可以做到 O(1) 修改了

由于询问是最后的所以只要最后 O(n) 的求两边前缀和就好了


代码:

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

typedef long long ll;
const int MAX_N = 10000005;

int n, m;
int pls[MAX_N];

inline int rd() {
    register int x = 0, c = getchar();
    register bool f = false;
    while (!isdigit(c)) {
        f = (c == '-');
        c = getchar();
    }
    while (isdigit(c)) {
        x = x * 10 + (c ^ 48);
        c = getchar();
    }
    return f ? -x : x;
}
inline ll rd_ll() {
    register ll x = 0;
    register int c = getchar();
    register bool f = false;
    while (!isdigit(c)) {
        f = (c == '-');
        c = getchar();
    }
    while (isdigit(c)) {
        x = x * 10 + (c ^ 48);
        c = getchar();
    }
    return f ? -x : x;
}

int main() {
    n = rd(); m = rd();
    register int l, r;
    register ll s, e, d;
    for (int i = 1; i <= m; ++i) {
        l = rd(); r = rd(); s = rd_ll(); e = rd_ll();
        d = (e - s) / (r - l);
        pls[l] += s;
        pls[l + 1] -= s - d;
        pls[r + 1] -= e + d;
        pls[r + 2] += e;
    }
    register ll d0 = 0, d1 = 0, xor_sig = 0, max_val = 0;
    for (int i = 1; i <= n; ++i) {
        d0 += (d1 += pls[i]);
        xor_sig ^= d0;
        max_val = max(max_val, d0);
    }
    printf("%lld %lld\n", xor_sig, max_val);
    return 0;
}
posted @ 2018-10-30 21:58  EvalonXing  阅读(155)  评论(0编辑  收藏  举报