【Codeforces 103D】Time to Raid Cowavans | 分块、离线处理

题目链接

题目大意:

给出一个序列 a a a,进行 Q Q Q次询问,每次询问 x , k x,k x,k

求出: ∑ c = 0 c ∗ k + x < = n a x + c ∗ k \sum_{c=0}^{c*k+x<=n}{a_{x+c*k}} c=0ck+x<=nax+ck

题目思路:

显然不太好维护这个东西。

但是可以考虑分块暴力一下,由于对于一个位置而言:

  1. 假设 k > s q r t ( n ) k \gt sqrt(n) k>sqrt(n),那么直接暴力即可,此时复杂度就是 ( n / k ) ≤ s q r t ( n ) (n/k) \le sqrt(n) (n/k)sqrt(n)
  2. 假设 k ≤ s q r t ( n ) k \le sqrt(n) ksqrt(n),此时下标集合的其实就是与 i i i在模 k k k相等同余系,所以可以直接暴力开一个 s q r t ( n ) ∗ s q r t ( n ) sqrt(n)*sqrt(n) sqrt(n)sqrt(n)的数组,代表对下标对 i i i取余为 k k k的数值总和,查询之后直接赋值就好了。

Code:

/*** keep hungry and calm CoolGuang!  ***/
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 3e5+700;
const ll mod= 1000000007;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int block  = 0;
ll sum[600][600];///对i取余为k的数量
ll a[maxn];
vector<pair<int,int>>v[maxn];
ll res[maxn];
int main(){
    
    	
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	block = sqrt(n);
	read(m);
	for(int i=1;i<=m;i++){
    
    
		int x,y;read(x);read(y);
		v[x].push_back({
    
    y,i});
	}
	for(int i=n;i>=1;i--){
    
    
		for(int k=1;k<=block;k++) sum[k][i%k] += a[i];
		for(auto x:v[i]){
    
    
			int id = x.second,w = x.first;
			if(w>block){
    
    
				ll ans = 0;
				for(int k=i;k<=n;k+=w) ans += a[k];
				res[id] = ans;
			}else res[id] = sum[w][i%w];
		}

	}
	for(int i=1;i<=m;i++) 
		printf("%lld\n",res[i]);
 	return 0;

}
/***
7
6 6 2 7 4 2 5
7
1 3 6
2 1 2 2
***/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/113199003