题目梗概
给定一个数组。
多次询问一个区间的和。
解题思路
这不是SB题
你要想想这是BZOJ的题目,请忽略A+B。
你没有足够的空间构造前缀和,但是你能存储下这个数组。
那就只能用分块了。
#include<cmath>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
inline int _read(){
int num=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
return num*f;
}
const int maxn=805,maxm=500005;
int n,m,t,fz,tot,w[maxm];
struct jz{
int id,x;
}a[maxn];
LL s[maxn],ans;
void work(){
a[0].x=1;int i=1;
while(i<=n){
int j=i;
if (j+fz<=n) j+=fz;else j=n+1;
tot++;a[tot].id=tot;a[tot].x=j;
while(i<j) s[tot]+=w[i]=_read(),i++;
}
}
int find(int x){
int L=1,R=tot,mid;
while (L<=R){
int mid=L+(R-L>>1);
if (a[mid-1].x<=x&&x<a[mid].x) return mid;
if (x<a[mid].x) R=mid-1;else L=mid+1;
}
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
n=_read(),m=_read(),t=_read();
fz=sqrt(n);
work();
for (int i=1;i<=m;i++){
int l=_read(),r=_read();
if (t==1) l=(l^abs(ans))%n+1,r=(r^abs(ans))%n+1;
if (r<l) swap(l,r);
int x=find(l),y=find(r);
ans=0;
if (x==y){for (int j=l;j<=r;j++) ans+=w[j];}else
{for (int j=l;j<a[x].x;j++) ans+=w[j];
for (int j=a[y-1].x;j<=r;j++) ans+=w[j];}
for (int j=x+1;j<=y-1;j++) ans+=s[j];
printf("%lld\n",ans);
}
return 0;
}