CF1883E

· · 题解

思路

首先,贪心不难发现 a 数组的值改动的越少越好。

不难想到暴力,将 a_i \times 2 直到 a_i > a_{i-1},但是复杂度不允许。

不妨优化,利用前缀和思想:如果后面的数比当前小,则一定会有重复的步骤在当前的数已经计算过。

运用前缀和的前提:

\forall a_i \Rightarrow \frac{a_i \times 2^x}{a_{i-1} \times 2^x}=\frac{a_i}{a_{i-1}}

t_ia_i 需要乘二的次数。

t_ia_ia_{i-1} 需要乘二的个数加上 t_{i-1}

结果为 \sum ^n_ {i=1} t_i

注意一点,如果 t_i<0,则 t_i=0

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<set>

using namespace std;

#define int long long
#define ll long long
#define Endl cout<<endl;
#define ENdl Endl
#define xy cout<<"xy";
#define yx cout<<"yx";
#define pii pair<int,int>
#define lowbit(x) x&(-x)
#define fi first
#define se second
#define fst ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

const int N=5e6+10;//注意修改
const int mod=1e9+7;
const int Max=0x3f3f3f3f3f;

int a[N];

void solve(){
    int n;
    cin>>n;
    int cnt=0,sum=0,ans=0;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=2;i<=n;i++){
        cnt=0;
        int l=a[i-1],r=a[i];
        //if(l<=r) continue;
        while(l<r) l*=2,cnt--;//少乘
        while(l>r) r*=2,cnt++;//多乘
        sum+=cnt;//最后乘多少
        if(sum<0) sum=0;//如果是负数,那就不用管
        ans+=sum;
    }

    cout<<ans<<endl;

}

/*
 */
signed main(){

//   freopen("a.in","r",stdin);
//   freopen("a.out","w",stdout);
    int T;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

/*
 1
 5 3
 2 4 5

 */