zoukankan      html  css  js  c++  java
  • [Codeforces 922E]Birds

    Description

    题库链接

    一条直线上有 (n) 棵树,每棵树上有 (c_i) 只鸟,在一棵树底下召唤一只鸟的魔法代价是 (cost_i) 每召唤一只鸟,魔法上限会增加 (B) 。从一棵树走到另一棵树,会增加魔法 (X) ,一开始的魔法和魔法上限都是 (W) 。问最多能够召唤的鸟的个数。

    (1leq nleq 1000,1leq B,X,Wleq 10^9,1leq sum_{i=1}^n c_ileq 10000)

    Solution

    容易想到记 (f_{i,j}) 为第 (i) 棵树时,召唤了 (j) 只鸟,剩余魔法的最大值。

    转移的话就是枚举 (j-c_i) 范围内的上一棵树的最大值。

    但这样复杂度似乎不太漂亮,考虑用单调队列优化,一个显然的“滑动窗口”模型。复杂度为 (O(nsum c)) 的。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1000, C = 10000;
    
    long long f[N+5][C+5], n, w, b, x, c[N+5], cost[N+5], tolc;
    int q[C+5], head, tail; bool v[N+5][C+5];
    
    void work() {
        scanf("%I64d%I64d%I64d%I64d", &n, &w, &b, &x);
        for (int i = 1; i <= n; i++) scanf("%I64d", &c[i]), tolc += c[i];
        for (int i = 1; i <= n; i++) scanf("%I64d", &cost[i]);
        f[0][0] = w; v[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= tolc; j++) f[i-1][j] = min(f[i-1][j]+x, w+b*j);
            head = tail = 0;
            for (int j = 0; j <= tolc; j++) {
                if (v[i-1][j]) {
                    while (head < tail && f[i-1][q[tail-1]]+cost[i]*q[tail-1] <= f[i-1][j]+cost[i]*j) --tail;
                    q[tail++] = j;
                }
                while (head < tail && j-q[head] > c[i]) ++head;
                if (head < tail && f[i-1][q[head]]+cost[i]*q[head]-cost[i]*j >= 0)
                    f[i][j] = f[i-1][q[head]]+cost[i]*q[head]-cost[i]*j, v[i][j] = 1;
            }
        }
        int ans = 0;
        for (int i = 0; i <= tolc; i++) if (v[n][i]) ans = i;
        printf("%d
    ", ans);
    }
    int main() {work(); return 0; }
  • 相关阅读:
    初识 vue
    Spring boot 整合 Swagger
    Swagger 注解
    初识 Swagger
    初识 mycat
    SpringBoot中的国际化
    为什么博客园用户体验这么差?
    Numpy常用方法及应用总汇
    嵌入式开发10种常见数字滤波算法
    .gitignore使用
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8682134.html
Copyright © 2011-2022 走看看