[Luogu 4231] 三步必杀

[Luogu 4231] 三步必杀

经某大佬的建议,蒟蒻去做了一下这道题,本人觉得这道题很有价值。

题意概括:

给定n个柱子,m次操作,每次操作会对l-r区间的损失度呈等差序列增加

(已给定对l增加的损失度s和对r增加的损失度e)求在m次操作后n根柱子损失度的异或和与最大值。

 

思路:

一开始想了很久的数据结构,

想过用树状数组,线段树等,

但后来发现什么数据结构都不用。。

因为是对一个区间加上等差数列,

所以我们想到了差分

即对l+1-r区间加,

对l和r+1这两个点做单点加,

可以用树状数组或线段树来维护,

但还有一种更简单的解法,

我们可以对这个差分序列再进行一次差分

这样一来就是进行四个单点加

分别是对l,l+1,r+1,r+2进行修改,

最后再对差分序列的差分序列求前缀和

得到的就是差分序列,

再对差分序列求一次前缀和,

得到的就是原数组。

最后记得要开long long!

<code>

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long 
#define rep(i,n,m) for(i=n;i<=m;i++)
int a[10000025],c[10000025];
int read(){
    int w=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') w=w*10+c-48,c=getchar();
    return w;
}
#undef int long long 
int main(){
#define int long long 
    int n,m,s,e,l,r,d,i,ans=0,maxn=0;
    n=read();m=read();
    rep(i,1,m){
        l=read();r=read();s=read();e=read();
        d=(e-s)/(r-l);
        a[l]+=s;a[l+1]+=d-s;
        a[r+1]+=-e-d;a[r+2]+=e;
    }
    rep(i,1,n){
        c[i]=c[i-1]+a[i];
        a[i]=a[i-1]+c[i];
        ans^=a[i];maxn=max(maxn,a[i]);
    }
    printf("%lld %lld",ans,maxn);
    return 0;
} 
Luogu 4231 三步必杀

 

posted @ 2020-08-08 22:15  Konnyaku  阅读(162)  评论(0编辑  收藏  举报