传送门: LOJ#6277.数列分块入门1
题意:给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。
另外,如图,输入挂能明显提高速率。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=50010;
typedef long long ll;
int n,a[maxn],tag[maxn];
int block,pos[maxn]; //pos[i]表示i属于哪个块
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;
}
void update(int l,int r,int c)
{
for(int i=l;i<=min(pos[l]*block,r);i++) //对于区间左半部分不完整的块进行暴力修改
a[i]+=c;
if(pos[l]!=pos[r])
for(int i=(pos[r]-1)*block+1;i<=r;i++) //对于右半部分不完整的块进行暴力修改
a[i]+=c;
for(int i=pos[l]+1;i<=pos[r]-1;i++) tag[i]+=c; //对于中间涉及的完整块标记即可
//给每个块设置一个加法标记tag[i](就是记录这个块中元素一起加了多少
}
int main()
{
//scanf("%d",&n);
n=read();
for(int i=1;i<=n;i++)
//scanf("%d",&a[i]);
a[i]=read();
block=sqrt(n); //每块的大小
for(int i=1;i<=n;i++)
pos[i]=(i-1)/block+1; //属于哪个块
for(int i=1;i<=n;i++)
{
int l,r,c,opt;
//scanf("%d%d%d%d",&opt,&l,&r,&c);
opt=read();
l=read();
r=read();
c=read();
if(opt==0)
update(l,r,c);
else
printf("%d\n",a[r]+tag[pos[r]]);
}
return 0;
}