题目描述 Description
给你N个数,有两种操作
1:给区间[a,b]的所有数都增加X
2:询问第i个数是什么?
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
1
2
3
2
1 2 3 2
2 3
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
1<=n<=100000
1<=q<=100000
线段树,单点查询+区间修改+标记下放
线段树代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define M 1000010
#define lch now*2
#define rch now*2+1
#define smid (l+r)/2
int a[M];
struct node{
int l,r,sum;
int bj;
};node sgt[M];
void build(int now,int l,int r) {//建树
sgt[now].l=l;
sgt[now].r=r;
if(l==r)
{
sgt[now].sum=a[l];
return;
}
build(lch,l,smid);
build(rch,smid+1,r);
sgt[now].sum=sgt[lch].sum+sgt[rch].sum;
}
void updata(int now) {//标记下放
sgt[lch].sum+=sgt[now].bj*(sgt[lch].r-sgt[lch].l+1);
sgt[rch].sum+=sgt[now].bj*(sgt[rch].r-sgt[rch].l+1);
sgt[lch].bj+=sgt[now].bj;
sgt[rch].bj+=sgt[now].bj;
sgt[now].bj=0;
}
void modify(int now,int l,int r,int v){//修改
if(l<=sgt[now].l&&sgt[now].r<=r){
sgt[now].bj+=v;
sgt[now].sum+=(sgt[now].r-sgt[now].l+1)*v;
return;
}
int mid=(sgt[now].l+sgt[now].r)>>1;
if(sgt[now].l==sgt[now].r) updata(now);
if(l<=mid) modify(lch,l,r,v);
if(r>mid) modify(rch,l,r,v);
//else return modify(lch,l,smid,v)+modify(rch,smid+1,r,v);
sgt[now].sum=sgt[lch].sum+sgt[rch].sum;
}
int query(int now,int l,int r){
if(l<=sgt[now].l&&r>=sgt[now].r)
return sgt[now].sum;
if(sgt[now].bj) updata(now);
int mid=(sgt[now].l+sgt[now].r)>>1;
if(l<=mid)return query(lch,l,r);
if(r>mid)return query(rch,l,r);
}
int main(){
int n,m,flag,x,y,v;
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++){
scanf("%d%",&flag);
if(flag==1) {
scanf("%d%d%d",&x,&y,&v);
modify(1,x,y,v);
}
else {
scanf("%d",&x);
printf("%d\n",query(1,x,x));
}
}
return 0;
}
树状数组也可以做
/*
和区间修改维护的东西不同.
差分思想,差分化区间修改为单点修改.
例:[2,5]+2 只需处+2 6处-2即可.
*/
#include<iostream>
#include<cstdio>
#define MAXN 100001
using namespace std;
int n,m,s[MAXN];
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
return x*f;
}
int lowbit(int t){
return t&-t;
}
void add(int x,int data){
while(x<=n){
s[x]+=data;
x+=lowbit(x);
}
}
int query(int x){
int tot=0;
while(x){
tot+=s[x];
x-=lowbit(x);
}
return tot;
}
int main()
{
int x,y,z,v;
n=read();
for(int i=1;i<=n;i++)
x=read(),add(i,x),add(i+1,-x);
m=read();
while(m--){
z=read();
if(z==1){
x=read();y=read();v=read();
add(x,v);add(y+1,-v);
}
else {
x=read();
printf("%d\n",query(x));
}
}
return 0;
}