这里采用了一个技巧,可以有效地避免了超时,记录一下前一个数乘2的数量,这是什么用处呢?举个例子:

7 1 5这个数组,首先1乘以3个二会大于7,记录pre=3,因为1* 2=2,2* 2=4,而4小于5,这意味着从5乘到大于等于8只需要1个2,因为1到五之间已经乘了两个2了,这就避免了许多不必要的运算。

就比如,当要改变的数组元素位置已经非常靠后面的情况下,显然它前一个数已经变得非常大,当前位置的元素又很不巧的是1,那么就需要很多次循环直到它再次大于前一个数为止,这样时间复杂度过高了,相比之下,直接在前一个数的乘2次数上修改时间复杂度大大下降

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
typedef long long ll;
ll a[M];
int main(){
    int t; cin>>t;
    while(t--){
        memset(a,0,sizeof(a));
        int n; cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        ll cnt=0; ll preb=0;
        for(int i=2;i<=n;i++){
            ll tmp=a[i];
            if(tmp<a[i-1]){
                while(tmp<a[i-1]){
                    tmp*=2;
                    preb++;
                }
            }
            else{
                while(tmp>=a[i-1]*2&&preb){
                    tmp/=2;
                    preb--;
                }
            }
            cnt+=preb;
        }
        cout<<cnt<<endl;
    }
    return 0;
}