• 优化 DP 专题


    ( ext{Example 1 : CF372C Watching Fireworks is Fun}) : 题目大意:城镇中有 个位置,有 (n) 个烟花要放。第 (i) 个烟花放出的时间记为 (t_i),放出的位置记为 (a_i)。如果烟花放出的时候,你处在位置 (x),那么你将收获 (b_i-|a_i-x|) 点快乐值。

    初始你可在任意位置,你每个单位时间可以移动不大于 (d) 个单位距离。现在你需要最大化你能获得的快乐值。

    首先很显然有一个 (N^2M) 的 DP,枚举 (i,j,k)(dp_{i,j}) 表示放第 (i) 个烟花时在位置 (j) 获得的最大快乐值,(k) 表示的是上一个烟花放时,人所在的位置。

    那么显然有 (dp_{i,j}=max{dp_{i-1,k}+ b_i - |a_i - j|})

    然后因为枚举 (i,j) 在前面,所以 (i,j) 有关的全部提出来。
    (dp_{i,j}=max{dp_{i-1,k}}+b_i-|a_i-j|) 就是得到的式子。

    然后就可以队列维护状态最大值然后转移了。
    如果你硬要拿 splay,线段树那我也没办法 ...

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    const int N = 1.5e5 + 10;
    const int M = 3e2 + 10;
    
    template <typename T> inline void read(T &ret) {
      ret = 0; char ch = getchar();
      while (!isdigit(ch)) ch = getchar();
      while (isdigit(ch)) ret = (ret<<1) + (ret<<3) + (ch^48), ch = getchar();
    }
    
    template <typename T, typename ... Args>
    inline void read(T &x, Args &... args) { read(x), read(args...); }
    
    int n, m, d, res = -1e18, que[N], dp[2][N];
    struct sect { int a, b, t; } p[M];
    
    inline void init() {
      memset(dp, 0xcf, sizeof dp);
      memset(que, 0, sizeof que);
      for (int i = 1; i <= n; ++i) dp[0][i] = 0;
    }
    
    inline void solve() {
      read(n, m, d); init();
      for (int i = 1; i <= m; ++i)
        read(p[i].a), read(p[i].b), read(p[i].t);
      for (int i = 1; i <= m; ++i) {
        int l = 1, r = 0, pos = 1, cur = i & 1;
        for (int j = 1; j <= n; ++j) {
          for (; pos <= min(n, j + d * (p[i].t - p[i - 1].t)); ++pos) {
            while (l <= r && dp[cur ^ 1][que[r]] <= dp[cur ^ 1][pos]) --r;
            que[++r] = pos;
          }
          while (l <= r && que[l] < max(j - d * (p[i].t - p[i - 1].t), 1LL)) ++l;
          dp[cur][j] = dp[cur ^ 1][que[l]] - abs(p[i].a - j) + p[i].b;
        }
      }
      for (int i = 1; i <= n; ++i) res = max(res, dp[m & 1][i]);
      printf("%lld
    ", res); return ;
    }
    
    signed main() { solve(); }
    
  • 相关阅读:
    POJ 1860 Currency Exchange【bellman_ford判断是否有正环——基础入门】
    POJ 3259 Wormholes【bellman_ford判断负环——基础入门题】
    hdu 4617 Weapon【异面直线距离——基础三维几何】
    POJ 3026 Borg Maze【BFS+最小生成树】
    POJ 1789 Truck History【最小生成树简单应用】
    POJ 2485 Highways【最小生成树最大权——简单模板】
    hdu 4627 The Unsolvable Problem【hdu2013多校3签到】
    POJ 1039 Pipe【经典线段与直线相交】
    POJ 1408 Fishnet【枚举+线段相交+叉积求面积】
    Rectangles
  • 原文地址:https://www.cnblogs.com/lbn233/p/Better-DP.html
Copyright © 2020-2023  润新知