Powered Addition(思维+贪心+位运算)Codeforces Round #633 (Div. 2)

在这里插入图片描述

题目大意

       给出一个长度为 n ( n < = 100000 ) n(n<=100000) n(n<=100000)的数组,在第 i i i秒时可以任意选出一些数使它们的值增加 2 i − 1 2^{i-1} 2i1,问如果要使得该数组不递减至少需要多少秒?

分析过程

       (感觉这道题挺妙的…… )我们经过分析可以发现,如果从左到右遍历数组,对于数组中碰到的第一组满足 a [ i ] > a [ i + 1 ] a[i]>a[i+1] a[i]>a[i+1]的两个相邻元素,我们必然要增加 a [ i + 1 ] a[i+1] a[i+1]来消除这个逆序,我们的最优贪心策略必然是使得 a [ i + 1 ] a[i+1] a[i+1]增加到与 a [ i ] a[i] a[i]相等,这样可以保证用的时间是最少的。这个时候,如果对于二进制位运算比较敏感的话,很容易察觉到,所用的时间就是 h i g h _ b i t ( x ) high\_ bit(x) high_bit(x),其中, x = a [ i ] − a [ i + 1 ] x=a[i]-a[i+1] x=a[i]a[i+1] h i g h _ b i t ( x ) high\_ bit(x) high_bit(x)表示 x x x对应的二进制位的最高位置(一个策略对应于一个二进制表示,以二进制位置表示时间,1或0表示是否叠加对应值。)。
       现在,我们一般化这个思路,在使得 a [ i + 1 ] = = a [ i ] a[i+1]==a[i] a[i+1]==a[i]之后,如果后面的值大于等于这个值那就自然满足不递减,这个时候我们就更新一下最大值(因为后面的值应该比左侧过来的最大值大),如果小于的话,我们更新一下答案,即 a n s = m a x ( a n s , h i g h _ b i t ( m a x i − a [ i ] ) ) ans=max(ans, high\_ bit(maxi-a[i])) ans=max(ans,high_bit(maxia[i]))

AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
typedef long long ll;
ll n, a[maxn], c[maxn];
ll high_bit(ll x){
	ll i = 63, e = 1;
	while(!(x & (e << i))) --i;
	return i + 1; 
}
void solve(){
	ll i, x, maxi = -10000000000, ans = 0;
	for(i=1;i<=n;++i){
		if(a[i] >= maxi) maxi = a[i];
		else{
			ll temp = high_bit(maxi - a[i]);
			ans = max(ans, temp);
		}
	}
	cout<<ans<<'\n';
}
int main(){
	int t, i, j;
	ios::sync_with_stdio(false);
	cin>>t;
	while(t--){
		cin>>n;
		for(i=1;i<=n;++i) cin>>a[i];
		solve();
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值