HDU 5945 / BestCoder Round #89 1002 Fxx and game 单调队列优化DP

Fxx and game

问题描述
 
青年理论计算机科学家Fxx给的学生设计了一款数字游戏。

一开始你将会得到一个数:XX,每次游戏将给定两个参数:k,tk,t, 任意时刻你可以对你的数执行下面两个步骤之一:

1.:X = X - i(1 <= i <= t)1.X=Xi(1<=i<=t)。

2.:2.:X:X:k:k的倍数,X = X / kX=X/k。

现在Fxx想要你告诉他最少的运行步骤,使:X:X变成:11。
输入描述
 
第一行一个整数:T(1leq Tleq20):T(1T20)表示数据组数。

接下来:T:T行,每行三个数:X,k,t(0leq tleq10^6,1leq X,kleq10^6)X,k,t(0t106​​,1X,k106​​)

数据保证有解。
输出描述
输出共:T:T行。

每行一个整数表示答案。
输入样例
2
9 2 1
11 3 3
输出样例
4
3

题解:

  看到题解眼泪掉下来

  

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 2e6+10, M = 2e5+20, mod = 1e9+7, inf = 2e9;

int X,k,t,dp[N],p[N];
int main() {
        int T;
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d%d",&X,&k,&t);
            for(int i = 2; i <= X; ++i) dp[i] = 0;
            dp[1] = 0;
            int l = 0,r = 0;
            p[1] = 1;l = r = 1;
            for(int i = 2; i <= X; ++i) {
                while(p[l] + t < i && l <= r) l++;
                dp[i] = inf;
                if(i % k == 0) dp[i] = dp[i/k] + 1;
                if (l<=r) dp[i] = min(dp[p[l]]+1,dp[i]);
                while(r - l >= 0 && dp[i] <= dp[p[r]]) r--;
                p[++r] = i;
            }
            printf("%d
",dp[X]);
        }
        return 0;
}
原文地址:https://www.cnblogs.com/zxhl/p/6011933.html