【HDU 5945】 Fxx and game 【单调队列优化dp】

来源:互联网 发布:网络潮州歌曲大全100首 编辑:程序博客网 时间:2024/06/07 15:51
题意:

http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=730&pid=1002 中文不解释。。

题解:

比赛的时候multiset写了一发过了初测就没细想了,没想到出题人卡了log

看到题解单调队列,很好写的一个dp

首先我们很容易得到状态转移方程dp[i]=(dp[k*i],dp[i+l])+1{1<=l<=t}

根据这个转移方程我们需要快速求得min{dp[i+l]}(1<=l<=t)

我们知道这种形式的就是单调队列优化dp的标准形式

维护一个dp[i]从队尾到队头递增的队列 

每次算好dp[i]的时候把队尾中dp值小于等于dp[i]的都出队(队列里面的都是下标比i大的,值又没i优,是无用的)

然后dp[i]=min(dp[q[head]],dp[k*i])+1

#include<set>#include<map>#include<cmath>#include<stack>#include<queue>#include<bitset>#include<vector>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define PB push_back#define MP make_pair#define ll long long#define MS(a,b) memset(a,b,sizeof(a))#define LL (rt<<1)#define RR (rt<<1|1)#define lson l,mid,LL#define rson mid+1,r,RR#define pii pair<int,int>#define pll pair<ll,ll>#define lb(x) (x&(-x))void In(){freopen("in.in","r",stdin);}void Out(){freopen("out.out","w",stdout);}const int N=1e6+10;const int M=3e5+10;const int Mbit=1e6+10;const int inf=0x3f3f3f3f;const ll mod=1e9+7;int dp[N],q[N];int main(){    int T,kase=0,x,k,t;    scanf("%d",&T);    while(T--){        int head=0,tail=0;        scanf("%d%d%d",&x,&k,&t);        MS(dp,0);        dp[x]=0;        q[tail++]=x;        for(int i=x-1;i>=1;i--){            dp[i]=dp[q[head]]+1;            if(1ll*k*i<=x)dp[i]=min(dp[i],dp[k*i]+1);            if(q[head]-t>=i&&head<tail)head++;///////////////////            while(tail>head&&dp[i]<=dp[q[tail-1]])tail--;            q[tail++]=i;        }        printf("%d\n",dp[1]);    }    return 0;}


0 0
原创粉丝点击