USETC B 一颗普通的线段树 裸线段树

B - 一棵普通的线段树

Time Limit: 4000 MS     Memory Limit: 256 MB
Submit Status

出题人明天就要半期考试了,课程是《火葬场与波》. 出题人倒在血泊中,一双有力的手摇晃着出题人的肩膀: “同志,醒醒,你还有题没出完呢”. 以下是他的遗言:

给你一个数组 A[1..n]A[1..n],初始值全为 0. 你需要写一棵裸的区间修改、区间查询的线段树, 以支持两个操作. 第一个操作是对区间 [L,R][L,R] 内的数每个数加上 vv. 第二个操作是给出区间 [L,R][L,R] 内所有数的和.

Input

第一行包含两个整数 n(1n106)n(1≤n≤106) 和 m(1m106)m(1≤m≤106), 分别是数组的大小和操作的个数.

接下来 mm 行,每行四个用空格分隔的整数 o l r v (1lrn,|v|103)o l r v (1≤l≤r≤n,|v|≤103). 如果 o=0o=0,则表示对区间 [l,r][l,r] 内每个数都加上 vv. 否则,请给出区间 [l,r][l,r] 内所有数的和,此时 v0v≡0.

Output

对于每个 o0o≠0 的操作, 输出包含一个整数的一行,表示对应区间内所有数的和.

Sample InputSample Output
5 4
0 2 4 5
1 3 5 0
0 1 3 -2
1 1 5 0
10
9

Sample input and output




























#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 100010;
int s[MAX_N<<2],col[MAX_N<<2];
void up(int p){
    s[p] = s[p*2] + s[p*2+1];
}
void build(int p,int l,int r){
    if(l==r){
        s[p] = 0;
        col[p] = 0;
        return ;
    }
    int mid =(l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    up(p);
}
void down(int p,int l,int r){
    if(col[p]){
        int mid =(l+r)>>1;
        col[p*2]+=col[p];
        col[p*2+1]+=col[p];
        s[p*2] += col[p]*(mid-l+1);
        s[p*2+1] += col[p]*(r-mid);
        col[p] = 0;
        return ;
    }
}
void change(int p,int l,int r,int x,int y,int v){
    if(x<=l&&r<=y){
        col[p] += v;
        s[p]+=(r-l+1)*v;
        return;
    }
    int mid = (l+r)>>1;
    down(p,l,r);
    if(x<=mid) change(p*2,l,mid,x,y,v);
    if(y>mid) change(p*2+1,mid+1,r,x,y,v);
    up(p);
}
int query(int p,int l,int r,int x,int y){
   if(x<=l&&r<=y){
    return s[p];
   }
   down(p,l,r);
   int mid = (l+r)>>1,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,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--){
        int a,b,c,v;
        scanf("%d%d%d%d",&a,&b,&c,&v);
        if(a==0){
            change(1,1,n,b,c,v);
        }
        else if(a==1){
            printf("%d\n",query(1,1,n,b,c));
        }
    }

    return 0;
}

阅读更多
个人分类: ACM DS-线段树
上一篇UESTC DS A 一颗简单的线段树 线段树
下一篇POJ 1990 MooFest 树状数组
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭