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

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

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

用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\n", ans[i]);
    }
    return;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work();
    return 0;
}

时间: 2024-10-03 23:53:09

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

【CF103D】Time to Raid Cowavans [根号算法]

CF103D Time to Raid Cowavans 一个序列\(a\),\(m\)次询问,每次询问给出\(t,k\),求\(a_t+a_{t+k}+a_{t+2k}+...+a_{t+pk},t+(p+1)k>n\) 步长\(k\ge\sqrt n\)时暴力枚举 \(k<\sqrt n\)时预处理出来部分和\(O(n\sqrt n)\) 但是这样会MLE 所以用一个\(sum\)数组 将询问离线询问 \(<\sqrt n\)的\(k\)不会超过\(\sqrt n\)个 所以复杂度不

Light OJ 1339 Strongest Community(分块暴力)

In a strange city, houses are built in a straight line one after another. There are several communities in the city. Each community consists of some consecutivehouses such that every house belongs to exactly one community. The houses are numbered fro

Codeforces#86D Powerful array(分块暴力)

Description An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?≤?l?≤?r?≤?n. For every positive integer s denote by Ks the number of occurrences of s into the subarray. We call the

CodeForces 103 D Time to Raid Cowavans

Time to Raid Cowavans 题意:一共有n头牛, 每头牛有一个重量,m次询问, 每次询问有a,b 求出 a,a+b,a+2b的牛的重量和. 题解:对于m次询问,b>sqrt(n)的时候我们直接把结果跑出来,当b<sqrt(n)的时候我们离线询问,算出所有一个b的任意一起点的值. 复杂度为 q*sqrt(n); 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen(&q

(分块暴力)Time to Raid Cowavans CodeForces - 103D

题意 给你一段长度为n(1 ≤ n ≤ 3·1e5)的序列,m (1 ≤ p ≤ 3·1e5)个询问,每次询问a,a+b,a+2b+...<=n的和 思路 一开始一直想也想不到怎么分,去维护哪些信息,看了题解才知道 其实分块不仅仅可以将一列序列分块,还可以将数据进行分块,下面讨论具体做法 首先这道题不是在线询问,可以离线做,先读入所有的询问,将询问从小到大排序①当b<√n时,对于每一个b我们可以预处理出这样的一个数组sum[i],就是以i为起点间隔为b的序列和(可以用一个简单的dp求出来),然

HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护

给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示dfs序,则R[i] - L[i] + 1 就是当前i这个节点拥有的子孙个数. 对于一颗树,dfs的时候,访问节点有先后顺序,那么可以用一个struct node List[maxn];表示这课树中访问的先后顺序. 例如这颗树,我假设是先访问0 --> 3 --> 2 ---> 4 ---&g

BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)

Bounce 弹飞绵羊 Time Limit:10000MS     Memory Limit:265216KB     64bit IO Format:%lld & %llu Submit Status Practice HYSBZ 2002 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后

D. Alyona and a tree 公式转换 + 分块暴力

http://codeforces.com/problemset/problem/740/D 对于每一对<u, v>.设dis[u]表示root到点u的距离,那么dis<u去v>就是dis[v] - dis[u], 就是在它的儿子中找出有多少个v使得dis[v] - dis[u] <= a[v].然后,因为如果v确定了,那么dis[v]和a[v]就确定了. 所以把公式转换为dis[v] - a[v] <= dis[u]. 那么可以暴力枚举每一个u,然后在其儿子中找有多少

Bzoj 3781: 小B的询问 莫队,分块,暴力

3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 426  Solved: 284[Submit][Status][Discuss] Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. Input 第一行,三个整数N.M.K. 第二行