题目描述
题解
这题卡内存,不能直接用前缀和
分块的话也只能开一些大小为块的个数的数组
难度不是很大,只需要做的时候小心一些就行了
不过ATP嫌我跑的太慢告诉我了一个较科学的方法,就是将块做一个前缀和,然后把块开小一点
代码
#include<algorithm>
#include<cstdio>
using namespace std;
#define LL long long
int n,m,opt,t,block,num,numl,numr;
int a[500005],L[800],R[800];
LL l,r,ans;
LL sum[800];
void query(int l,int r)
{
numl=(l-1)/block+1,numr=(r-1)/block+1;
if (numl==numr)
{
for (int i=l;i<=r;++i) ans+=(LL)a[i];
return;
}
if (l==L[numl]) l=numl;
else
{
for (int i=l;i<=R[numl];++i)
ans+=(LL)a[i];
l=numl+1;
}
if (r==R[numr]) r=numr;
else
{
for (int i=L[numr];i<=r;++i)
ans+=(LL)a[i];
r=numr-1;
}
for (int i=l;i<=r;++i) ans+=sum[i];
return;
}
int main()
{
scanf("%d%d%d",&n,&m,&opt);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
block=707;t=(n-1)/block+1;
L[1]=1,R[1]=block;
for (int i=2;i<=t;++i)
{
L[i]=L[i-1]+block;
R[i]=R[i-1]+block;
}R[t]=n;
for (int i=1;i<=t;++i)
for (int j=L[i];j<=R[i];++j)
sum[i]+=(LL)a[j];
for (int i=1;i<=m;++i)
{
scanf("%lld%lld",&l,&r);
if (ans<0) ans=-ans;
if (opt)
{
l=(l^ans)%n+1;
r=(r^ans)%n+1;
if (l>r) swap(l,r);
}
ans=0LL;query(l,r);
printf("%lld\n",ans);
}
}