题目描述 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 <bits/stdc++.h>
#define N 100001
int n,m;
int a[N];
int main()
{
int t,x,y,z;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&t);
if(t==1)
{
scanf("%d %d %d",&x,&y,&z);
for(int j=x;j<=y;j++)
a[j]=a[j]+z;
}
else
{
scanf("%d",&x);
printf("%d\n",a[x]);
}
}
}
线段树
#include <bits/stdc++.h>
#define N 100005
struct TREE
{
int l,r,c,lazy;
}t[N * 4];
void build(int l,int r,int pos)
{
t[pos].l = l;
t[pos].r = r;
if (t[pos].l == t[pos].r)
return ;
int mid = (l + r) >> 1;
build(l,mid,pos * 2);
build(mid + 1,r,pos * 2 + 1);
}
void add(int num,int pos,int p)
{
if (t[p].l == t[p].r && t[p].r == pos)
{
t[p].c = num;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
if (pos > mid)
add(num,pos,p * 2 + 1);
else add(num,pos,p * 2);
}
void pushDown(int pos)
{
t[pos * 2 + 1].lazy += t[pos].lazy;
t[pos * 2].lazy += t[pos].lazy;
t[pos].lazy = 0;
}
void addSum(int l,int r,int c,int p)
{
if (t[p].l == l && t[p].r == r)
{
t[p].lazy += c;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
pushDown(p);
if (l > mid)
addSum(l,r,c,p * 2 + 1);
else
if (r <= mid)
addSum(l,r,c,p * 2);
else
{
addSum(l,mid,c,p * 2);
addSum(mid + 1,r,c,p * 2 + 1);
}
}
int find(int pos,int p)
{
if (t[p].l == t[p].r && t[p].r == pos)
{
return t[p].c + t[p].lazy;
}
pushDown(p);
int mid = (t[p].l + t[p].r) >> 1;
if (pos > mid)
return find(pos,p * 2 + 1);
else return find(pos,p * 2);
}
int main()
{
int n,Q;
scanf("%d",&n);
build(1,n,1);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d",&x);
add(x,i,1);
}
scanf("%d",&Q);
for (int i = 1; i <= Q; i++)
{
int k;
scanf("%d",&k);
if (k == 1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addSum(x,y,z,1);
}
else
{
int pos;
scanf("%d",&pos);
printf("%d\n",find(pos,1));
}
}
}
树状数组
#include <bits/stdc++.h>
int c[200000];
int n,m,t,x,y,z;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int y)
{
while(x<=n)
{
c[x]=c[x]+y;
x=x+lowbit(x);
}
}
int getsum(int x)
{
int s=0;
while(x>=1)
{
s=s+c[x];
x=x-lowbit(x);
}
return s;
}
int main()
{
scanf("%d",&n);
y=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
add(i,x-y);
y=x;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&t);
if(t==1)
{
scanf("%d %d %d",&x,&y,&z);
add(x,z);
add(y+1,-z);
}
else
{
scanf("%d",&x);
printf("%d\n",getsum(x));
}
}
}