题目描述
给你N个数,有两种操作1:给区间[a,b]的所有数都增加X;2:询问第i个数是什么?
输入描述
第一行一个正整数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
数据范围及提示
数据范围
1<=n<=100000
1<=q<=100000
解题思路:这道题目线段树模板,其中点查询用区间查询的方式。
#include <cstdio>
#define ll long long
using namespace std;
struct TREE{
int l,r;
ll sum,lazy;
}tree[400005];
int n,m,b,c,d,a[100005];
inline int read()
{
ll f=1,x=0;
char ch=getchar();
if (ch=='-')
{
f=-1;
ch=getchar();
}
while ((ch<'0')||(ch>'9')) ch=getchar();
while ((ch>='0')&&(ch<='9'))
{
x=x*10+ch-48;
ch=getchar();
}
return f*x;
}
inline void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if (l==r)
{
tree[root].sum=a[l];
return;
}
int mid=(l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
inline void js(int root,int l,int r,int d)
{
tree[root].lazy+=d;
tree[root].sum+=d*(r-l+1);
}
inline void push_down(int root,int l,int r)
{
int mid=(l+r)/2;
js(root*2,l,mid,tree[root].lazy);
js(root*2+1,mid+1,r,tree[root].lazy);
tree[root].lazy=0;
}
inline void change(int root,int l,int r)
{
int nl=tree[root].l,nr=tree[root].r;
int mid=(nl+nr)/2;
if ((l<=nl)&&(nr<=r))
{
tree[root].sum+=d*(nr-nl+1);
tree[root].lazy+=d;
return;
}
push_down(root,nl,nr);
if (l<=mid) change(root*2,l,r);
if (r>mid) change(root*2+1,l,r);
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
inline ll find(int root,int l,int r)
{
int nl=tree[root].l,nr=tree[root].r;
int mid=(nl+nr)/2;
ll s=0;
if ((l<=nl)&&(nr<=r)) return tree[root].sum;
push_down(root,nl,nr);
if (l<=mid) s+=find(root*2,l,r);
if (r>mid) s+=find(root*2+1,l,r);
return s;
}
int main()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
m=read();
for (int i=1;i<=m;i++)
{
int x;
x=read();
if (x==1)
{
b=read(),c=read(),d=read();
change(1,b,c);
} else
{
b=read();
printf("%lld\n",find(1,b,b));
}
}
return 0;
}