CodeForces - 1339C Powered Addition

You have an array a of length n. For every positive integer x you are going to perform the following operation during the x-th second:

Select some distinct indices i1,i2,…,ik which are between 1 and n inclusive, and add 2x−1 to each corresponding position of a. Formally, aij:=aij+2x−1 for j=1,2,…,k. Note that you are allowed to not select any indices at all.
You have to make a nondecreasing as fast as possible. Find the smallest number T such that you can make the array nondecreasing after at most T seconds.

Array a is nondecreasing if and only if a1≤a2≤…≤an.

You have to answer t independent test cases.

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

The first line of each test case contains single integer n (1≤n≤105) — the length of array a. It is guaranteed that the sum of values of n over all test cases in the input does not exceed 105.

The second line of each test case contains n integers a1,a2,…,an (−109≤ai≤109).

Output
For each test case, print the minimum number of seconds in which you can make a nondecreasing.

Example
Input
3
4
1 7 6 5
5
1 2 3 4 5
2
0 -4
Output
2
0
3
Note
In the first test case, if you select indices 3,4 at the 1-st second and 4 at the 2-nd second, then a will become [1,7,7,8]. There are some other possible ways to make a nondecreasing in 2 seconds, but you can’t do it faster.

In the second test case, a is already nondecreasing, so answer is 0.

In the third test case, if you do nothing at first 2 seconds and select index 2 at the 3-rd second, a will become [0,0].

题目大意:给出一个由 n 个数组成的数列 a,选择一个最小的 k ,代表可以进行 k 次操作,对于第 t 次操作可以选择任意个位置使得 a[ i ] = a[ i ] + 2^( t - 1 ),问最少需要多少次操作才能使序列满足非严格递增

题目分析:读完题后的第一反应是模拟+贪心,实际上不是的,需要想到的一个知识点是,任何数字都可以用二进制来表示,相应的题目中的操作可以转换为二进制加法,进而转换为:对于某个位置,都可以加上任何一个数

因为需要让整个序列非严格递增,所以取任意两个位置 i 和 j 满足 i < j 讨论一下:

如果 a[ i ] <= a[ j ] :显然已经满足题目要求,无需操作
如果 a[ i ] > a[ j ] :让 a[ j ] 加上一个数变为 a[ i ] 显然是最优的
这样一来我们只需要维护一下前缀的最大值,对于后续的每个 a[ i ] ,找出最大的差值就好了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define LL long long

using namespace std;
const int INF = 0x3f3f3f3f;

int main(int argc,char* argv[]) {
    int T,n,num;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        int Max = -INF, Dec = -INF;
        for(int i=1; i<=n; i++) {
            scanf("%d",&num);
            Max = max(Max,num);
            Dec = max(Dec,Max - num);
        }
        LL Ans = 0;
        while((1LL << Ans) - 1 < Dec) Ans ++;
        printf("%lld\n",Ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值