線段樹,區間求和,求平方和,同乘同加
阿新 • • 發佈:2018-12-13
qn姐姐最好了~
qn姐姐給你了一個長度為n的序列還有m次操作讓你玩,
1 l r 詢問區間[l,r]內的元素和
2 l r 詢問區間[l,r]內的元素的平方 和
3 l r x 將區間[l,r]內的每一個元素都乘上x
4 l r x 將區間[l,r]內的每一個元素都加上x
輸入描述:
第一行兩個數n,m 接下來一行n個數表示初始序列 就下來m行每行第一個數為操作方法opt, 若opt=1或者opt=2,則之後跟著兩個數為l,r 若opt=3或者opt=4,則之後跟著三個數為l,r,x 操作意思為題目描述裡說的
輸出描述:
對於每一個操作1,2,輸出一行表示答案
示例1
輸入
5 6 1 2 3 4 5 1 1 5 2 1 5 3 1 2 1 4 1 3 2 1 1 4 2 2 3
輸出
15 55 16 41
備註:
對於100%的資料 n=10000,m=200000 (注意是等於號) 保證所有詢問的答案在long long 範圍內
sum1[i] 表示區間和,sum2[i]表示區間平方和
add[i]表示同加延遲標記,mul[i]表示同乘延遲標記
注意更新延遲標記的時候,mul會對add產生影響
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 typedef long long ll; const int mx = 10005; int n,m; ll add[mx<<2],mul[mx<<2],sum1[mx<<2],sum2[mx<<2]; ll a[mx]; void pushup(int rt){ sum1[rt] = sum1[rt<<1] + sum1[rt<<1|1]; sum2[rt] = sum2[rt<<1] + sum2[rt<<1|1]; } void build(int l,int r,int rt){ sum1[rt] = sum2[rt] = 0; add[rt] = 0; mul[rt] = 1; if(l == r){ sum1[rt] = a[l]; sum2[rt] = a[l]*a[l]; return ; } int mid = (l+r)>>1; build(lson); build(rson); pushup(rt); } void pushdown(int rt,int len){ add[rt<<1] = add[rt] + add[rt<<1]*mul[rt]; add[rt<<1|1] = add[rt] + add[rt<<1|1]*mul[rt]; sum2[rt<<1] += 2*add[rt]*sum1[rt<<1] + (len-(len>>1))*add[rt]*add[rt]; sum2[rt<<1|1] += 2*add[rt]*sum1[rt<<1|1] + (len>>1)*add[rt]*add[rt]; sum1[rt<<1] = add[rt]*(len-(len>>1)) + sum1[rt<<1]*mul[rt]; sum1[rt<<1|1] = add[rt]*(len>>1) + sum1[rt<<1|1]*mul[rt]; mul[rt<<1] *= mul[rt]; mul[rt<<1|1] *= mul[rt]; mul[rt] = 1; add[rt] = 0; } void update(int l,int r,int rt,int L,int R,int val,int type){ if(l >= L && r <= R){ if(type == 3){ mul[rt] *= val; add[rt] *= val; sum1[rt] *= val; sum2[rt] *= (val*val); return ; }else{ add[rt] += val; sum2[rt] += (2*val*sum1[rt] + val*val*(r-l+1)); sum1[rt] += (val*(r-l+1)); return ; } } pushdown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid) update(lson,L,R,val,type); if(R > mid) update(rson,L,R,val,type); pushup(rt); } ll q1,q2; ll res; void query(int l,int r,int rt,int L,int R){ if(l >= L && r <= R){ q1 += sum1[rt]; q2 += sum2[rt]; return ; } int mid = (l+r)>>1; res = 0; pushdown(rt,r-l+1); if(L <= mid) query(lson,L,R); if(R > mid) query(rson,L,R); //pushup(rt); } int main(){ while(~scanf("%d%d",&n,&m)){ for(int i = 1; i <= n; i++){ scanf("%lld",&a[i]); } build(1,n,1); int op,l,r; ll v; while(m--){ scanf("%d",&op); q1 = q2 = res = 0; if(op == 1){ scanf("%d%d",&l,&r); query(1,n,1,l,r); printf("%lld\n",q1); } else if(op == 2){ scanf("%d%d",&l,&r); query(1,n,1,l,r); printf("%lld\n",q2); } else if(op == 3){ scanf("%d%d%lld",&l,&r,&v); update(1,n,1,l,r,v,3); } else if(op == 4){ scanf("%d%d%lld",&l,&r,&v); update(1,n,1,l,r,v,4); } } } }