【CodeForces - 305C】Ivan and Powers of Two(思維)
C. Ivan and Powers of Two
time limit per test
0.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Ivan has got an array of n non-negative integers a1, a2, ..., an. Ivan knows that the array is sorted in the non-decreasing order.
Ivan wrote out integers on a piece of paper. Now he wonders, what minimum number of integers of form (b ≥ 0) need to be added to the piece of paper so that the sum of all integers written on the paper equalled - 1 for some integer v (v ≥ 0).
Help Ivan, find the required quantity of numbers.
Input
The first line contains integer n (1 ≤ n ≤ 105). The second input line contains n space-separated integers a1, a2, ..., an (0 ≤ ai ≤ 2·109). It is guaranteed that a1 ≤ a2 ≤ ... ≤ an.
Output
Print a single integer — the answer to the problem.
Examples
input
Copy
4 0 1 1 1
output
Copy
0
input
Copy
1 3
output
Copy
3
Note
In the first sample you do not need to add anything, the sum of numbers already equals - 1 = 7.
In the second sample you need to add numbers .
思路:
一開始沒想到怎麼做,但是看資料量這麼大就一定是思維題,寫了寫發現要求得就是許多個的加和,並且和還是2的指數,而由2的指數得到2的指數,那就是兩個相同的相加使得指數加1。即,因此我們只要暴力遍歷所有的數,找相鄰兩個數之間的差值就是我們要補的數的多少,如果一對數是1,3那麼我們新增幾個數後應該變為4(使得兩個數變為1個)。小的數在不斷新增數的過程中會增加,直到和大的數相等,這時我們不必在加新的數,只需要這兩個數相加就好。由此我們能發現要補的數是t1、t1+1....t2-1()。因此這兩個數之間需要補的數是t2-t1個。
這裡我用來優先佇列,但是直接用陣列模擬應該也是可以的。greater從小到大的優先順序佇列。
ac程式碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<string.h>
#define ll long long
using namespace std;
priority_queue<ll,vector<ll>,greater<ll> > que;
ll a[110100];
int main()
{
int n;
scanf("%d",&n);
a[0]=0;
que.push(0);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
que.push(a[i]);
}
ll ans=0;
while(!que.empty())
{
ll t1=que.top();
que.pop();
ll t2=que.top();
que.pop();
if(t1==t2)
{
if(que.empty())
{
break;
}
else
{
que.push(t1+1);
}
}
else
{
int dis=t2-t1;
ans+=dis;
if(que.empty())
{
break;
}
else
{
que.push(t2+1);
}
}
}
cout<<ans<<endl;
return 0;
}
cf上大佬們寫的程式碼就行簡單,自己寫的還是太麻煩了,ORZ。
個人的理解:
感覺就是,0~v時,我一開時什麼都沒有,然後從0~v需要0~v-1這幾個數和0這個數。而0我一開始有1個
那麼0~v-1一共有v個那麼我一開始缺少k個。然後讀入數後進行合併並放入set中,那麼set中是我現在有的,即我不用再額外找這些數了。
但是set中的最大值就是v,而這個本來就不需要,因此不應該算在已有的裡面,所以現在已有的是s.size()-1。
需要的-已經有的=要補的
#include<bits/stdc++.h>
using namespace std;
set<int> s;
int a,n,k;
int main(){
cin>>n;
while (n--){
cin>>a;
while (s.count(a))
s.erase(a),a++;
s.insert(a),
k=max(k,a);//能到的最大值,應該就是v 讀入的數的最大值再加一
}
cout<<k-s.size()+1;
}