[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; }