[Luogu 4231] 三步必殺
阿新 • • 發佈:2020-08-09
經某大佬的建議,蒟蒻去做了一下這道題,本人覺得這道題很有價值。
題意概括:
給定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++) intLuogu 4231 三步必殺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; }