测试地址:Time to Raid Cowavans
题目大意:维护一个长为的数列,要求处理个询问,每次询问给出一个数对,询问的值,其中但。
做法:本题需要用到分块+离线处理。
直接的暴力肯定是会炸的,需要考虑优化。
我们发现对于的询问,每次暴力求值的复杂度不超过,总复杂度为,可以接受。
重点是处理的询问,我们可以对于每个不同的值,对所有我们处理出题目要求的后缀和,这样就可以回答询问了。对于每个值都是的复杂度,而值共有种,所以总复杂度为。
但是的空间复杂度对于70MB的空间限制来说太大了,注意到题目没有强制在线,所以我们在一开始将所有询问对排序,然后顺次处理下来,这样空间复杂度就降为,可以接受。这样我们就以的复杂度解决了这一问题。
(实际上我不太清楚这个题到底是不是真正的分块思想,如果标错了请见谅)
以下是本人代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,sq,m;
ll a[300010],ans[300010],sum[300010];
struct Query
{
int id,a,b;
}q[300010];
bool cmp(Query a,Query b)
{
return a.b<b.b;
}
int main()
{
scanf("%d",&n);
sq=(int)sqrt(n);
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
q[i].id=i;
scanf("%d%d",&q[i].a,&q[i].b);
}
q[0].b=0;
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)
{
if (q[i].b<sq)
{
if (q[i].b!=q[i-1].b)
{
for(int j=n;j>=1;j--)
{
if (j>n-q[i].b) sum[j]=a[j];
else sum[j]=sum[j+q[i].b]+a[j];
}
}
ans[q[i].id]=sum[q[i].a];
}
else
{
ans[q[i].id]=0;
for(int j=q[i].a;j<=n;j+=q[i].b)
ans[q[i].id]+=a[j];
}
}
for(int i=1;i<=m;i++)
printf("%I64d
",ans[i]);
return 0;
}