题目分析
当初打bestcoder的时候我用广搜写的,并且我知道会超时,但是因为那天脑子太昏了不知道怎么优化,赛后rejudge果然tle。这道题就是用单点队列存放当前位置的前t个位置中最小的那个,代码很懂,也很容易理解,这里就不多说了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e6+100;
const int INF = 0x3f3f3f3f;
int dp[maxn], que[maxn];
int main(){
int T;
scanf("%d", &T);
int x, k, t;
while(T--){
scanf("%d%d%d", &x, &k, &t);
memset(dp, INF, sizeof(dp));
int head = 0, tail = -1;
dp[1] = 0;
que[++tail] = 1; //单调队列里面存放的是位置
for(int i = 2; i <= x; i++){
if(i%k == 0) dp[i] = min(dp[i], dp[i/k]+1);
while(head <= tail && i - que[head] > t) head++; //保证队列中只有当前位置之前的t个元素
dp[i] = min(dp[i], dp[que[head]]+1); //如果队列不位空
while(head <= tail && dp[que[tail]] > dp[i]) tail--; //保证队列为单调递增队列
que[++tail] = i;
}
printf("%d\n", dp[x]);
}
return 0;
}