zkw線段樹模板練習。

orz今天寫了三遍

另外我只寫了區間修改和求和。爲啥呢?因爲我菜啊qwq

#include<iostream>
#include<cstdio>
#define maxn 200001
#define int long long
using namespace std;
int n, m;
int sum[maxn*2], add[maxn*2]; 
void build(){
    for(m=1; m<=n; m<<=1);
    for(int i=m+1; i<=m+n; i++)
        scanf("%lld", &sum[i]);
    for(int i=m-1; i; i--)
        sum[i]=sum[i<<1]+sum[i<<1|1];
}
inline int query_part(int s, int t){
    int lc=0, rc=0, len=1, ans=0;
    for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
        if(s&1^1) ans+=sum[s^1]+len*add[s^1], lc+=len;
        if(t&1) ans+=sum[t^1]+len*add[t^1], rc+=len;
        if(add[s>>1]) ans+=add[s>>1]*lc;
        if(add[t>>1]) ans+=add[t>>1]*rc;
    }
    s>>=1; 
    for(lc+=rc; s; s>>=1)
        if(add[s]) ans+=add[s]*lc;
    return ans;
}
inline int update(int s, int t, int v){
    int lc=0, rc=0, len=1;
    for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
        if(s&1^1) add[s^1]+=v, lc+=len;
        if(t&1)   add[t^1]+=v, rc+=len;
        sum[s>>1]+=v*lc, sum[t>>1]+=v*rc;
    }
    for(lc+=rc; s; s>>=1)
        sum[s>>1]+=v*lc;
}
int q;
signed main(){
    scanf("%lld%lld", &n, &q);
    build();
    int qwq, x, y, k;
    while(q--){
        scanf("%lld", &qwq);
        if(qwq==1){
            scanf("%lld%lld%lld", &x, &y, &k);
            update(x, y, k);
        }else{
            scanf("%lld%lld", &x, &y);
            printf("%lld\n", query_part(x, y));
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章