线段树模板(单点 区间) POJ 3468

正在思考人缘关系的WNJXYK忽然被数学老师点起来回答问题了,数学老师知道他走神了于是想出个难一点的问题惩罚他。

数学老师一转身,黑板上就出现了一个长度为N的序列 A1, A2, … , AN ,数学老师以谢尔曼M1坦克每分钟350发
穿甲、爆破燃烧,瞬间完成的速度要求WNJXYK完成他如下的若干操作:
1.给这个序列一段区间每个位置增减同一个数字
2.询问一个区间的和

令人惊讶的是WNJXYK总能立刻给出回答,但是老师却无法验证他是不是在口胡,于是他想让你写个程序帮助他。

Input
第一行包含两个数字N,Q(1N,Q ≤ 100000)
第二行包含N个数字,表示数列的初始状态。( -1000000000 ≤ Ai ≤ 1000000000)
接下来Q行,每行一个操作:
"C a b c" 表示给 Aa, Aa+1, … , Ab. 每个位置的数字增加c (-10000 ≤ c ≤ 10000"Q a b" 表示询问 Aa, Aa+1, … , Ab. 的区间和

Output
输出若干行,开始你的表演。

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

Sample Output
5
55
15
30

Hint
区间和有可能超过32位整型

本题使用区间模拟即可,下面是模板 根据题意相应修改判断即可

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MAX_N=100000;
const ll INF = 0x3f3f3f3f;


ll tree[800000];
ll lazy[802020];
//初始化
void init(ll n){
    for(ll i=0;i<n*4;i++){
        tree[i]=0;
    }
}
//建树
void build(ll l,ll r,ll root){
    if(l==r){
        cin>>tree[root];
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,root<<1);
    build(mid+1,r,root<<1|1);
    tree[root]=tree[root<<1]+tree[root<<1|1];
}
//lazy更新处理 
void PushDown(ll root,ll m){
    if(lazy[root]){
        lazy[root<<1]+=lazy[root];//注意这里是+=  修改换成=即可
        lazy[root<<1|1]+=lazy[root];//注意这里是+=  修改换成=即可
        tree[root<<1]+=(m-(m>>1))*lazy[root];//注意这里是+=  修改换成=即可
        tree[root<<1|1]+=(m>>1)*lazy[root];//注意这里是+=  修改换成=即可
        lazy[root]=0;
    }
}
//区间更改
void changearea(ll l,ll r,ll root,ll L,ll R,ll val){
    if(L<=l&&R>=r){
        lazy[root]+=val;//注意这里是+=  修改换成=即可
        tree[root]+=(ll)val*(r-l+1);//注意这里是+=  修改换成=即可
        return;
    }
    PushDown(root,r-l+1);
    ll mid=(l+r)>>1;
    if(L<=mid)
        changearea(l,mid,root<<1,L,R,val);
    if(R>mid)
        changearea(mid+1,r,root<<1|1,L,R,val);
    tree[root]=tree[root<<1]+tree[root<<1|1];
}

//单点修改
void changepoint(ll l,ll r,ll root,ll poll,ll val){
    if(l==r){
        tree[root]+=val;
        return;
    }
    ll mid=(l+r)>>1;
    if(poll<=mid)
        changepoint(l,mid,root<<1,poll,val);
    else    
        changepoint(mid+1,r,root<<1|1,poll,val);
    tree[root]=tree[root*2]+tree[root*2+1];
}


//区间查询(带lazy标记)
ll searcharea(ll l,ll r,ll root,ll L,ll R){
    if(L<=l&&R>=r)
        return tree[root];
    PushDown(root,r-l+1);
    ll mid=(l+r)>>1;
    if(R<=mid)
        return searcharea(l,mid,root<<1,L,R);
    if(L>mid)
        return searcharea(mid+1,r,root<<1|1,L,R);
    else
        return searcharea(l,mid,root<<1,L,mid)+searcharea(mid+1,r,root<<1|1,mid+1,R); 
}
//区间查询(单点)
ll searchpoint(ll l,ll r,ll root,ll L,ll R){
    if(L<=l&&R>=r)
        return tree[root];
    ll mid=(l+r)>>1;
    if(R<=mid)
        return searchpoint(l,mid,root<<1,L,R);
    else if(L>mid)
        return searchpoint(mid+1,r,root<<1|1,L,R);
    else
        return searchpoint(l,mid,root<<1,L,mid)+searchpoint(mid+1,r,root<<1|1,mid+1,R); 
} 
int main(){
    ios::sync_with_stdio(false);
    ll n,q;
    cin>>n>>q;
    init(n);
    build(1,n,1);
    string s;
    ll a,b,c;
    for(ll i=0;i<q;i++){
        cin>>s;
        if(s=="Q"){
            cin>>a>>b;
            cout<<searcharea(1,n,1,a,b)<<endl;
        }
        else{
            cin>>a>>b>>c;
            changearea(1,n,1,a,b,c);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38842456/article/details/79835387