P4544 [USACO10NOV] Buying Feed G ( 单调队列dp

#include
using namespace std;
using VI = vector;
using ll = long long;
int k,e,n;
struct shop{
    ll x,f,c;
    bool operator < (const shop &u){
        return x < u.x;
    }
}s[510];
ll dp[2][10010];
int q[10010];
int cur,pre;
//f[i][j] = f[i-1][k] + k * (x[i] - x[i-1]) + c * (j - k)
//f[i][j] = min(f[i-1][k] + k * (x[i] - x[i-1]) - c * k) + c * j

ll calc(int k , int p){
    return dp[pre][k] + k * k * (s[p].x - s[p-1].x) - s[p].c * k;
}


int main(){
    cin>>k>>e>>n;
    for(int i = 1 ; i <= n ; i++){
        cin>>s[i].x>>s[i].f>>s[i].c;
    }
    sort(s + 1 , s + 1 + n);
    memset(dp , 2 ,sizeof dp);
    dp[0][0] = 0;
    for(int i = 1; i <= n ; i++){
        cur = i % 2;
        pre = (i + 1) % 2;
        int hh = 1 , tt = 0 ;
        for(int j = 0 ; j <= k ; j++){
            while(hh <= tt && calc(q[tt],i) > calc(j,i))tt--;
            while(hh <= tt && q[hh] + s[i].f < j) hh++;
            q[++tt] = j;
            dp[cur][j] = calc(q[hh] , i) + s[i].c * j;
        }

    }
    printf("%lld" , dp[n%2][k] + (ll)(k * k) * (ll)(e - s[n].x));

}

你可能感兴趣的:(dp,算法,动态规划,图论)