计蒜客习题:区间整数操作

问题描述

给出 N 个整数 A1,A2,…,AN,你需要处理区间加,区间求和。
输入格式
第一行两个整数 N 和 Q (1≤N,Q≤10^5)。
第二行 N 个整数,表示 A1,A2…AN(∣Ai∣≤10^9)的初始值。
接下来 Q 行,每行一个操作:
C a b c,表示 Aa,Aa+1…Ab 每个数加 c (∣c∣≤10000)。
Q a b,表示询问 Aa,Aa+1…Ab 的和,答案可能超过 32 位整数。
输出格式
对于所有 Q 询问,一行输出一个答案。
样例输入

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

样例输出

4
55
9
15

AC代码

#include 
#include 
using namespace std;
const int MAX_N=(1e5)+50;
long long int s[MAX_N*4];
long long int col[MAX_N*4];

void up(int p){
    s[p]=s[p*2]+s[p*2+1];
    return;
}

void down(int p,int l,int r){
    if(col[p]){
        int mid=(l+r)/2;
        s[p*2]+=col[p]*(mid-l+1);
        s[p*2+1]+=col[p]*(r-mid);
        col[p*2]+=col[p];
        col[p*2+1]+=col[p];
        col[p]=0;
    }
    return;
}

void molify(int p,int l,int r,int x,int y,int v){
    if(l>=x&&r<=y){
        col[p]+=v;
        s[p]+=v*(r-l+1);
        return;
    }
    down(p,l,r);
    int mid=(l+r)/2;
    if(x<=mid)molify(p*2,l,mid,x,y,v);
    if(y>mid)molify(p*2+1,mid+1,r,x,y,v);
    up(p);
    return;
}

long long query(int p,int l,int r,int x,int y){
    if(l>=x&&r<=y){
        return s[p];
    }
    down(p,l,r);
    int mid=(l+r)/2;
    long long int res=0;
    if(x<=mid)res+=query(p*2,l,mid,x,y);
    if(y>mid)res+=query(p*2+1,mid+1,r,x,y);
    return res;
}


int main(){
    int N,Q;
    cin>>N>>Q;
    for(int i=1;i<=N;i++){
        int d;
        scanf("%d",&d);
        molify(1,1,N,i,i,d);
    }
    for(int i=1;i<=Q;i++){
        char X;
        scanf(" %c",&X);
        if(X=='C'){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            molify(1,1,N,a,b,c);
        }else{
            int a,b;
            scanf("%d%d",&a,&b);
            cout<1,1,N,a,b)<return 0;
}

你可能感兴趣的:(算法竞赛刷题,#,树状数组,计蒜客NOIP习题)