luogu P4231 三步必杀

分析

一开始想到差分+线段树,好像数据太大,拿不满分
于是看到了题解里某各路大佬都讲一个高端名词曰:二阶差分
何为二阶差分?就是对差分数组进行差分
乍一眼看去好像没用,但是手推一下会发现牛逼的地方
(图小,大佬轻喷)
luogu P4231 三步必杀
我们发现,原数组要加上一个等差数列,而一阶差分只需区间均加,而二阶差分更恐怖,只需要修改4个数。。。

从图中不难推得:

l,r,s,ed设l,r,s,e如题意,且公差为d
c则对于二阶差分数组c
c[l]+=sc[l]+=s

c[l+1]+=dsc[l+1]+=d-s

c[r+1]+=dec[r+1]+=-d-e

c[r+2]+=ec[r+2]+=e

于是这道题,就很简单了
先利用攻击数据构造二阶差分数组,然后输出答案时求两次前缀和(注意是前缀和,这是差分的性质)即可

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;i++)
#define clean(arry,num); memset(arry,num,sizeof(arry));
#define ll long long
#define max(a,b) ((a>b)?a:b)
ll n,m;
const int maxn=1e7+10;
ll a[maxn],b[maxn],c[maxn];
inline ll read()
{
    ll ans=0;bool neg=false;char r=getchar();
    while(r>'9'||r<'0'){if(r=='-')neg=true;r=getchar();}
    while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}
    return (neg)?-ans:ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("datain.txt","r",stdin);
    #endif
    n=read();m=read();
    clean(a,0);clean(b,0);clean(c,0);
    loop(i,1,m)
    {
        int l,r,s,e;l=read();r=read();s=read();e=read();
        int d=(e-s)/(r-l);//方差
        c[l]+=s;
        c[l+1]+=d-s;
        c[r+1]+=-e-d;
        c[r+2]+=e;
    }
    ll res,maxx=-0x7f7f;
    loop(i,1,n)
    {
        b[i]=b[i-1]+c[i];
        a[i]=a[i-1]+b[i];//求前缀和
        maxx=max(maxx,a[i]);
        if(i!=1)res^=a[i];//按题意求异或和
        else res=a[i];
    }
    printf("%lld %lld",res,maxx);
    return 0;
}

相关文章:

  • 2021-08-31
  • 2021-09-27
  • 2022-02-28
  • 2022-01-03
  • 2022-02-15
  • 2021-07-12
  • 2021-06-03
  • 2022-01-21
猜你喜欢
  • 2021-05-24
  • 2021-11-07
  • 2022-12-23
  • 2021-09-23
  • 2022-03-01
  • 2021-07-05
相关资源
相似解决方案