题目链接:Time to Raid Cowavans
题目大意:给你一个长度为n的序列w,求w[x] + w[x+y] + w[x+2y] + … + w[x + py],其中x+py <= n。
然后因为区间不是连续的,我们不能用线段树,BIT之类的数据结构去优化。
于是我们可以想到分块,我们对 mod 的值分块,然后对于块的大小大于根号就直接暴力,否则把答案的mod值存起来,然后枚举mod的值,O(n)计算当前mod 的值的答案。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int N=3e5+10;
int n,m,w[N],bl,res[N],sum[N<<1];
vector<pair<int,int> > v[N];
signed main(){
cin>>n; bl=sqrt(n);
for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
scanf("%lld",&m);
for(int i=1,x,y;i<=m;i++){
scanf("%lld %lld",&x,&y);
if(y>bl){
for(int j=x;j<=n;j+=y) res[i]+=w[j];
}else v[y].push_back({x,i});
}
for(int i=1;i<=bl;i++){
if(!v[i].size()) continue; memset(sum,0,sizeof sum);
for(int j=n;j>=1;j--) sum[j]+=sum[j+i]+w[j];
for(int j=0;j<v[i].size();j++) res[v[i][j].second]=sum[v[i][j].first];
}
for(int i=1;i<=m;i++) printf("%lld\n",res[i]);
return 0;
}