• 洛谷 P3957 跳房子 二分+DP检验+单调队列优化


    题意:有n个格子,第i个格子距离起点xi得分si,有一个机器人只能跳d的距离,花1金币可以增加1灵活度,问要得到k分至少需要多少金币

    1 ≤ n ≤ 5e5, 1 ≤ d ≤2000, 1 ≤ xi, k ≤ 1e9, |si| < 1e5

    思路:花多少金币的决策有单调性,所以先二分答案,用dp检验,设dp[i]表示在第i个格子获得的最大分数

    容易看出dp[i] = max(dp[k])+s[i],k能走到i,显然不优化是n^2的复杂度

    但也比较显然这就是单调队列优化的模型(P1725),于是nlogn AC

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<queue>
     6 #define INF 0x3f3f3f3f
     7 #define LL long long
     8 #define debug(x) cout << "[" << x << "]" << endl
     9 using namespace std;
    10 
    11 const int mx = 5e5+10;
    12 int x[mx], s[mx];
    13 LL dp[mx];
    14 int n, k, d;
    15 
    16 bool check(int g){
    17     deque<int> q;
    18     int p = 0, l = max(1, d-g), r = d+g;
    19     for (int i = 1; i <= n; i++){
    20         dp[i] = -INF;
    21         while (x[i]-x[p] >= l && p < i){
    22             while (!q.empty() && dp[p] >= dp[q.back()]) q.pop_back();
    23             q.push_back(p++);
    24         }
    25         while (!q.empty() && x[i]-x[q.front()] > r) q.pop_front();
    26         if (q.empty() || dp[q.front()] == -INF) continue;
    27         dp[i] = dp[q.front()]+s[i];
    28         if (dp[i] >= k) return 1;
    29     }
    30     return 0;
    31 }
    32 
    33 int main(){
    34     scanf("%d%d%d", &n, &d, &k);
    35     for (int i = 1; i <= n; i++)
    36         scanf("%d%d", &x[i], &s[i]);
    37     int l = 0, r = 2e9, ans = -1;
    38     while (l <= r){
    39         int mid = l+(r-l)/2;
    40         if (check(mid)) {
    41             ans = mid;
    42             r = mid-1;
    43         }
    44         else l = mid+1;
    45     }
    46     printf("%d
    ", ans);
    47     return 0;
    48 }
  • 相关阅读:
    MEP工作流程
    一盘很大的棋
    老人棒子鸡
    REVIT多专业协同设计
    不做没有理想的咸鱼
    卫生间排风设计规范
    如何时刻保持在目标的正确轨道上
    OGame殖民
    OGame舰队保护(FleetSave, FS)
    在局域网内架ESS3.0升级服务器
  • 原文地址:https://www.cnblogs.com/QAQorz/p/9759764.html
Copyright © 2020-2023  润新知