zoukankan      html  css  js  c++  java
  • SCOI 2010 股票交易 (单调队列优化dp)

    (f[i][j]) 表示前 (i) 天,当前有 (j) 股的最大值

    啥也不干: (f[i][j] = f[i - 1][j])

    直接买: (j in [0,as[i]] f[i][j] = -j * ap[i])

    (i)(i - w - 1) 的基础上买

    (f[i][j] = max(f[i - w - 1][k] - (j - k) * ap[i]))

    (k in [j - as[i], j])

    (i)(i - w - 1) 的基础上卖

    (f[i][j] = max(f[i - w - 1][k] + (k - j) * bp[i]))

    (k in [j, j + bs[i]])

    显然可以通过单调队列优化,时间复杂度 (O(np))

    #include <map>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <vector>
    #include <bitset>
    #include <cstdio>
    #include <cctype>
    #include <string>
    #include <numeric>
    #include <cstring>
    #include <cassert>
    #include <climits>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std ;
    //#define int long long
    #define rep(i, a, b) for (int i = (a); i <= (b); i++)
    #define per(i, a, b) for (int i = (a); i >= (b); i--)
    #define loop(s, v, it) for (s::iterator it = v.begin(); it != v.end(); it++)
    #define cont(i, x) for (int i = head[x]; i; i = e[i].nxt)
    #define clr(a) memset(a, 0, sizeof(a))
    #define ass(a, sum) memset(a, sum, sizeof(a))
    #define lowbit(x) (x & -x)
    #define all(x) x.begin(), x.end()
    #define ub upper_bound
    #define lb lower_bound
    #define pq priority_queue
    #define mp make_pair
    #define pb push_back
    #define pof pop_front
    #define pob pop_back
    #define fi first
    #define se second
    #define iv inline void
    #define enter cout << endl
    #define siz(x) ((int)x.size())
    #define file(x) freopen(#x".in", "r", stdin),freopen(#x".out", "w", stdout)
    typedef long long ll ;
    typedef unsigned long long ull ;
    typedef pair <int, int> pii ;
    typedef vector <int> vi ;
    typedef vector <pii> vii ;
    typedef queue <int> qi ;
    typedef queue <pii> qii ;
    typedef set <int> si ;
    typedef map <int, int> mii ;
    typedef map <string, int> msi ;
    const int N = 2010 ;
    const int INF = 0x3f3f3f3f ;
    const int iinf = 1 << 30 ;
    const ll linf = 2e18 ;
    const int MOD = 1000000007 ;
    const double eps = 1e-7 ;
    void print(int x) { cout << x << endl ; exit(0) ; }
    void PRINT(string x) { cout << x << endl ; exit(0) ; }
    void douout(double x){ printf("%lf
    ", x + 0.0000000001) ; }
    template <class T> void chmin(T &a, T b) { if (a > b) a = b ; }
    template <class T> void chmax(T &a, T b) { if (a < b) a = b ; }
    template <class T> void upd(T &a, T b) { (a += b) %= MOD ; }
    template <class T> void mul(T &a, T b) { a = (ll) a * b % MOD ; }
    
    int n, p, w, ans = -iinf ;
    int ap[N], bp[N], as[N], bs[N], q[N] ;
    int f[N][N] ;
    int hd, tl ;
    
    signed main(){
        scanf("%d%d%d", &n, &p, &w) ;
        rep(i, 1, n) scanf("%d%d%d%d", &ap[i], &bp[i], &as[i], &bs[i]) ;
        ass(f, 0xcf) ;
    	rep(i, 1, n) {
    		rep(j, 0, as[i]) f[i][j] = -j * ap[i] ;
    		rep(j, 0, p) chmax(f[i][j], f[i - 1][j]) ;
    		if (i - w <= 1) continue ;
    		hd = 1, tl = 0 ;
    		rep(j, 0, p) {
    			while (hd <= tl && q[hd] < j - as[i]) hd++ ;
    			if (hd <= tl) { // isn't empty
    				int k = q[hd] ;
    				chmax(f[i][j], f[i - w - 1][k] + (k - j) * ap[i]) ;
    			}
    			while (hd <= tl && f[i - w - 1][q[tl]] + q[tl] * ap[i] <= f[i - w - 1][j] + j * ap[i]) tl-- ;
    			q[++tl] = j ;
    		}
    		hd = 1, tl = 0 ;
    		per(j, p, 0) {
    			while (hd <= tl && q[hd] > j + bs[i]) hd++ ;
    			if (hd <= tl) {
    				int k = q[hd] ;
    				chmax(f[i][j], f[i - w - 1][k] + (k - j) * bp[i]) ;
    			}
    			while (hd <= tl && f[i - w - 1][q[tl]] + q[tl] * bp[i] <= f[i - w - 1][j] + j * bp[i]) tl-- ;
    			q[++tl] = j ;
    		}
    	}
    	rep(i, 0, p) ans = max(ans, f[n][i]) ;
    	printf("%d
    ", ans) ;
    	return 0 ;
    }
    
    /*
    f[i][j] 表示前 i 天,当前有 j 股的最大值
    啥也不干: f[i][j] = f[i - 1][j]
    直接买: j ∈[0, as[i]] f[i][j] = -j * ap[i]
    i 在 i - w - 1 的基础上买:
    f[i][j] = max(f[i - w - 1][k] - (j - k) * ap[i]) (k ∈ [j - as[i], j])
    i 在 i - w - 1 的基础上卖:
    f[i][j] = max(f[i - w - 1][k] + (k - j) * bp[i]) (k ∈ [j, j + bs[i]])
    */
    
    /*
    写代码时请注意:
    	1.ll?数组大小,边界?数据范围?
    	2.精度?
    	3.特判?
    	4.至少做一些
    思考提醒:
    	1.最大值最小->二分?
    	2.可以贪心么?不行dp可以么
    	3.可以优化么
    	4.维护区间用什么数据结构?
    	5.统计方案是用dp?模了么?
    	6.逆向思维?
    */
    
    加油ヾ(◍°∇°◍)ノ゙
  • 相关阅读:
    Chrome cookies folder
    Fat URLs Client Identification
    User Login Client Identification
    Client IP Address Client Identification
    HTTP Headers Client Identification
    The Personal Touch Client Identification 个性化接触 客户识别
    购物车 cookie session
    购物车删除商品,总价变化 innerHTML = ''并没有删除节点,内容仍存在
    453
    购物车-删除单行商品-HTMLTableElement.deleteRow()
  • 原文地址:https://www.cnblogs.com/harryhqg/p/10621925.html
Copyright © 2011-2022 走看看