Question:
这题分块
这里的删除线有点毒瘤啊。。。
我们设一个block[]表示第i位属于哪个块。
我们便可以这样子打:
st=sqrt(n);
for (int i=1;i<=n;i++) bl[i]=(i-1)/st+1;
然后,对于opt==0
我们发现它除了整个块,但两边可能会有一点点的多出来(就是不够一整个块)
这两边我们可以暴力搞,而中间的,我们便存一个b[]表示第i块整体加了多少。
for (int i=l;i<=min(bl[l]*st,r);i++) a[i]+=c;
if (bl[l]!=bl[r])
for (int i=(bl[r]-1)*st+1;i<=r;i++) a[i]+=c;
for (int j=bl[l]+1;j<=bl[r]-1;j++) b[j]+=c;
对于opt==1
呵呵,简单,直接输出a[r]+b[block[r]] 即可。
完整代码如下:
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[50010],b[231],opt,l,r,c,st;
int bl[50010];
inline int read()
{
int x=0,f=0; char c=getchar();
while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f ? -x:x;
}
void add(int l,int r,int c)
{
for (int i=l;i<=min(bl[l]*st,r);i++) a[i]+=c;
if (bl[l]!=bl[r])
for (int i=(bl[r]-1)*st+1;i<=r;i++) a[i]+=c;
for (int j=bl[l]+1;j<=bl[r]-1;j++) b[j]+=c;
}
int main()
{
freopen("6277.in","r",stdin);
freopen("6277.out","w",stdout);
n=read();st=sqrt(n);
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++) bl[i]=(i-1)/st+1;
for (int i=1;i<=n;i++)
{
opt=read(),l=read(),r=read(),c=read();
if (opt==0) add(l,r,c);
else printf("%d
",a[r]+b[bl[r]]);
}
return 0;
}