题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数数加上x
2.求出某一个数的值
输入输出格式
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含2或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x 含义:输出第x个数的值
输出格式:
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
输入样例#1: 复制
5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4
输出样例#1: 复制
6 10
这是一道树状数组模版题,但是今天学了一下分块,就用分块试了试,感觉还可以
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll read()
{
ll 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-'0';ch=getchar();}
return x*f;
}
int n,blo;
int v[500005],bl[500005],atag[500005];
void add(int a,int b,int c)
{
for(int i=a;i<=min(bl[a]*blo,b);i++)
v[i]+=c;
if(bl[a]!=bl[b])
for(int i=(bl[b]-1)*blo+1;i<=b;i++)
v[i]+=c;
for(int i=bl[a]+1;i<=bl[b]-1;i++)
atag[i]+=c;
}
int main()
{
n=read();int m=read();blo=sqrt(n);
for(int i=1;i<=n;i++)v[i]=read();
for(int i=1;i<=n;i++)bl[i]=(i-1)/blo+1;
while(m--)
{
int f=read();
if(f==1)
{
int a,b,c;
a=read();b=read();c=read();
add(a,b,c);
}
if(f==2)
{
int b;
b=read();
printf("%d\n",v[b]+atag[bl[b]]);
}
}
return 0;
}