题目描述
给你N个数,有两种操作1:给区间[a,b]的所有数都增加X;2:询问第i个数是什么?
输入描述
第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。
输出描述
对于每个询问输出一行一个答案
扫描二维码关注公众号,回复:
1016049 查看本文章
样例输入
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; }