码迷,mamicode.com
首页 > 其他好文 > 详细

G - Most Dangerous Shark dp 单调栈 单调队列

时间:2020-01-26 16:02:35      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:单调队列   def   out   sha   高度   alt   题解   isp   names   

 

题意:

一条线段上有n张骨牌(n=1e7), 相邻骨牌距离为1,每张骨牌有其高度和推倒的花费,问最少的花费推倒所有的骨牌。

题解:

  • 首先用单调栈维护每个位置往左(右)推能推倒的最远的骨牌
  • dp[i]表示1-i倒下的最小花费
  • 转移显然只有两种  一种是第i张往左推动
  • 另一种是找到往右推动能推倒i的最小花费的地方进行转移  这里可以用单调栈维护最小值
技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+1000;

ll n,m,siz[N],h[N],L[N],R[N],c[N],dp[N];
vector<ll>H[N],C[N];
int s[N],r;

int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        scanf("%lld",&siz[i]);
        H[i].resize(siz[i]);
        C[i].resize(siz[i]);
        for(int j=0;j<siz[i];j++) scanf("%lld",&H[i][j]);
        for(int j=0;j<siz[i];j++) scanf("%lld",&C[i][j]);
    }
    int Q;cin>>Q;
    int cnt=0;
    while(Q--) {
        int id,mul;scanf("%d%d",&id,&mul);
        for(int j=0;j<siz[id];j++) h[++cnt]=H[id][j],c[cnt]=C[id][j]*mul;
    }
    for(int i=1;i<=m;i++) {
        while(r&&h[s[r]]+s[r]<=i)
            R[s[r--]]=i-1;
        s[++r]=i;
    }
    while(r) R[s[r--]]=m;
    for(int i=m;i;i--) {
        while(r&&s[r]-h[s[r]]>=i)
            L[s[r--]]=i+1;
        s[++r]=i;
    }
    while(r) L[s[r--]]=1;

    for(int i=1;i<=m;i++) {
        dp[i]=c[i]+dp[L[i]-1];
        while(r&&R[s[r]]<i) r--;
        if(r) dp[i]=min(dp[i],c[s[r]]+dp[s[r]-1]);
        ll cost=c[i]+dp[i-1];
        if(r&&cost<c[s[r]]+dp[s[r]-1]||!r)
            s[++r]=i;
    }
    cout<<dp[m];
}
View Code

 

G - Most Dangerous Shark dp 单调栈 单调队列

标签:单调队列   def   out   sha   高度   alt   题解   isp   names   

原文地址:https://www.cnblogs.com/bxd123/p/12234275.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!