牛客網小白月賽5
阿新 • • 發佈:2019-01-31
目描述
Apojacsleam喜歡陣列。
他現在有一個n個元素的陣列a,而他要對a[L]-a[R]進行M次操作:
操作一:將a[L]-a[R]內的元素都加上P
操作二:將a[L]-a[R]內的元素都減去P
最後詢問a[l]-a[r]內的元素之和?
請認真看題幹及輸入描述。
輸入描述:
輸入共M+3行: 第一行兩個數,n,M,意義如“題目描述” 第二行n個數,描述陣列。 第3-M+2行,共M行,每行四個數,q,L,R,P,若q為1則表示執行操作2,否則為執行操作1 第4行,兩個正整數l,r
輸出描述:
一個正整數,為a[l]-a[r]內的元素之和
示例1
輸入
10 5 1 2 3 4 5 6 7 8 9 10 1 1 5 5 1 2 3 6 0 2 5 5 0 2 5 8 1 4 9 6 2 7
輸出
23
開始看到這道題目上去第一反應線段樹模板程式碼,然後就陷入了記憶體超限和WA的死迴圈,從開始的30%一直到最後的%90...WA了七八次...
到後面實在想不到解決方案了就百度了一下這道題的解法, 發現原來還有字首和這種美滋滋的東西, 簡直妙蛙種子啊~~~
關鍵點: 因為最後只要查詢一次,在過程中僅僅只需要對這一段距離進行操作,因為輸入順序的關係可以現將操作的數給儲存下來,到後面在統一進行操作, 然後用一個數事先計算出L - R的和,然後每次操作就僅僅只對這個和進行操作。
秒啊~~~~~~
下面附上程式碼
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; const int maxn = 1000001; int sz[maxn]; int q[maxn],l[maxn],r[maxn],p[maxn]; int n,m; int tl,tr; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",sz+i); for(int i=1;i<=m;i++) scanf("%d%d%d%d",q+i,l+i,r+i,p+i); scanf("%d%d",&tl,&tr); ll sum=0; for(int i=tl;i<=tr;i++) sum += sz[i]; for(int i=1;i<=m;i++){ if(q[i] == 1) p[i] = 0-p[i]; if(r[i]<tl || l[i]>tr) continue; sum += (min(r[i],tr) - max(l[i],tl) + 1)*p[i]; } printf("%lld",sum); return 0; }