Codeforces Round #633 (Div. 2) C. Powered Addition(假模拟真思维)

题目链接

题目大意

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

题目思路

读完题后的第一反应是模拟+贪心,实际上不是的,一直wa,我的思路就是如果a[j]<premax,那么就要加(1<<i)一直wa

举一个反例 如
2 -1 -3 -4 第一步变为 2 0 -2 -3 第二步 2 2 0 -1 第三步 2 2 4 3 第四步 2 2 4 11那么答案就是4步,其实答案应该是3
2 -1 -3 -4第一步2 0 -3 -3 第二步 2 2 -1 -1 第三步 2 2 3 3

需要想到的一个知识点是,任何数字都可以用二进制来表示,相应的题目中的操作可以转换为二进制加法,进而转换为:对于某个位置,都可以加上任何一个数

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

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

代码

#include<map>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#include<algorithm>
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
int t,n,a[maxn];
int cal(int x){
    int cnt=0;
    while(x>0){//求x变为二进制中最大的那一位
        x=x/2;
        cnt++;
    }
    return cnt;
}
int main(){
    scanf("%d",&t);
    while(t--){
        int premax=0,chamax=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        premax=a[1];
        for(int i=2;i<=n;i++){
            chamax=max(chamax,premax-a[i]);
            premax=max(premax,a[i]);//前面的最大值
        }
        printf("%d\n",cal(chamax));
    }
    return 0;
}

参考链接:https://blog.csdn.net/qq_45458915/article/details/105485767?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值