题意:把音量从p调到q,
若 q >= p,一直按着每次音量上升1
若 q < p ,每次按着的那一秒下降1,接下来一秒下降2,4,8....(2x),x是前一秒下降的值。中途可以选择按键停止或up上升
求 p -> q的最小时间。
思路:枚举 2^tx-1 > q - p,选择降到q的下方或上方,然后逼近。
做多校时由于一直想着按up要加+1所以做了两边dfs,一直tle,看了题解才恍然大悟:
以下是看过标程写的代码:记录stop,停下多少次,不管有没有up,如果最终跳到q的下方,所有向上+1的作用都可以和从q下面到q的时间抵消。(所以不用考虑一开始先向上再下来)
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll dfs(int now ,int goal,int stop,ll ans){
if(now == goal) return ans;
int tx = 0;
while(now - (1<<tx) + 1 > goal) tx++;
//与q点重合
if(now - (1<<tx)+1 == goal) return ans + tx;
//在q点下方
ll dis = goal - max(0LL,(ll)now-(1<<tx)+1);
ll tm = tx + max(0LL,(ll)(dis - stop));
//在q点上方
return min(ans + tm ,dfs(now - (1<<(tx-1)) + 1 ,goal,stop+1,ans+tx));
}
int main()
{
//freopen("in.txt","r",stdin);
int p,q,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&p,&q);
if(q>=p){
printf("%lld\n",(ll)(q - p));
}
else{
printf("%lld\n",dfs(p,q,0,0LL));
}
}
return 0;
}