C. Powered Addition
传送门(题目地址)http://codeforces.com/contest/1339/problem/C
Input
3
4
1 7 6 5
5
1 2 3 4 5
2
0 -4
Output
2
0
3
题意:
本题要求你把数组变成递增。每分钟可以选择任意数组元素增加2^(n-1);求花费最少的时间,
思路
1. 由于数据量很大,所以只能想办法在o(n)内解决。即遍历数组。
2. 那就先从第1个元素开始遍历,如果找到不满足题意得,那就说明这点时要进行操作得,(a[i]<a[i-1])所以对这一点贪心得操作,(根据等比数列:首项是1,公比是2。这个数列可以从中构成任意数正整数->那么就贪心的把这个不满足的a[i]增加为a【i-1】)
3. 一个数组元素所能改变的最大值就是过的时间 t 对应的等比数列前n想和
4. 因为是对任意数组元素操作,所以线性操作,把i->更新ans后,后面的元素如果时间不够,再增加ans(时间)
5. 而如何算时间呢,我先打了个表,把等比数列前n项和 的1~64的值打印 出来。
6. 具体看我的while操作,以标记出来,
7. ans就是时间了
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn];
ll time[maxn];
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
ll temp=1;
for(int i=1; i<=60; i++)
{
temp*=2;
time[i]=temp-1;
}
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1; i<=n; i++)cin>>a[i];
ll pre=a[1];//前一个元素
ll ans=0;
ll temp=0;
for(int i=2; i<=n; i++)
{
if(a[i]<pre)
{
temp=a[i]+time[ans];
while(temp<pre)//对a【i】进行操作,直到它大于pre
{
ans++;//加了后还小,才会循环,不够,就再加一秒
temp=a[i]+time[ans];
}
}
else pre=a[i];
}
cout<<ans<<endl;
}
return 0;
}