【线段树】单点求值+区间修改

来源:互联网 发布:ubuntu虚拟机文件共享 编辑:程序博客网 时间:2024/06/12 17:00
#include<iostream>#include<cstdio>using namespace std;int n,m,a[1000004];struct data{int l,r,val,lazy,len;}tr[2*1000004];void build(int k,int s,int t) {//建树    tr[k].l=s;tr[k].r=t;tr[k].len=t-s+1;    if(s==t) {tr[k].val=a[s];return;}    int mid=(s+t)>>1;    build(k<<1,s,mid);    build(k<<1|1,mid+1,t);    tr[k].val=tr[k<<1].val+tr[k<<1|1].val;}//区间修改void pushdown(int k){    if(!tr[k].lazy) return;    int p=tr[k].lazy;    tr[k<<1].lazy+=p;    tr[k<<1|1].lazy+=p;    tr[k<<1].val+=tr[k<<1].len*p;    tr[k<<1|1].val+=tr[k<<1|1].len*p;    tr[k].lazy=0;}void update(int k,int l,int r,int addval){    int ll=tr[k].l,rr=tr[k].r;    if(ll>=l && rr<=r){        tr[k].lazy+=addval;        tr[k].val+=tr[k].len*addval;        return;    }    int mid=(ll+rr)>>1;        if (tr[k].lazy) pushdown(k);    if(l<=mid) update(k<<1,l,min(r,mid),addval);    if(r>mid) update(k<<1|1,max(l,mid+1),r,addval);    tr[k].val=tr[k<<1].val+tr[k<<1|1].val;}int query1(int k,int x){//单点查询    int ll=tr[k].l,rr=tr[k].r;    if(ll==rr) return tr[k].val;    int mid=(ll+rr)>>1;    if (tr[k].lazy) pushdown(k);    if(x<=mid) return query1(k<<1,x);    else return query1(k<<1|1,x);}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    build(1,1,n);    scanf("%d",&m);    for(int i=1;i<=m;i++){        int flag;scanf("%d",&flag);        int x,y,z;scanf("%d",&x);        if(flag==1) scanf("%d%d",&y,&z),update(1,x,y,z);        else printf("%d\n",query1(1,x));    }    return 0;}

Laoj1298

输入格式
第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出格式
对于每个询问输出一行一个答案

输入示例
3
1
2
3
2
1 2 3 2
2 3
输出示例
5

原创粉丝点击