题目链接: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;
}