D. Time to Raid Cowavans 分块暴力,感觉关键在dp

http://codeforces.com/contest/103/problem/D

对于b大于 sqrt(n)的,暴力处理的话,那么算出每个的复杂度是sqrt(n),就是把n分成了sqrt(n)段,

其他的,b小于sqrt(n)的,那么不同 b值最多只有sqrt(n)个,但是询问可能达到q个。考虑到,如果b相同的话,放在一起,能不能记录一个结果呢?如果能,那么就最多是sqrt(n)个不同的询问。

用dp[pos]表示从pos这个位置开始,间隔为b的答案值。

那么需要从后面往前dp,每次转移dp[i] = dp[i + b] + a[i]即可

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
int magic;
int n;
const int maxn = 3e5 + 20;
int a[maxn];
struct node {
    int a, b;
    int id;
    bool operator < (const struct node &rhs) const {
        return b < rhs.b;
    }
}query[maxn];
LL ans[maxn];
LL dp[maxn];
void work() {
    scanf("%d", &n);
    magic = (int)sqrt(n * 1.0);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    int q;
    scanf("%d", &q);
    for (int i = 1; i <= q; ++i) {
        scanf("%d%d", &query[i].a, &query[i].b);
        query[i].id = i;
    }
    sort(query + 1, query + 1 + q);
    int last = -1;
    for (int i = 1; i <= q; ++i) {
        if (query[i].b >= magic) {
            for (int j = query[i].a; j <= n; j += query[i].b) {
                ans[query[i].id] += a[j];
            }
        } else {
            if (query[i].b == last) {
                ans[query[i].id] = dp[query[i].a];
            } else {
//                cout << query[i].a << " " << query[i].b << endl;
                last = query[i].b;
                for (int j = n; j >= 1; --j) {
                    if (j + query[i].b > n) {
                        dp[j] = a[j];
                    } else {
                        dp[j] = dp[j + query[i].b] + a[j];
                    }
                }
                ans[query[i].id] = dp[query[i].a];
            }
        }
    }
//    for (int i = 1; i <= n; ++i) {
//        printf("%I64d ", dp[i]);
//    }
//    cout << endl;
    for (int i = 1; i <= q; ++i) {
        printf("%I64d
", ans[i]);
    }
    return;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5927430.html