1. 程式人生 > 實用技巧 >[Luogu 4231] 三步必殺

[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 三步必殺