您的位置:首页 > 其它

codeforces-372A

2016-02-26 16:36 381 查看
题目:

There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaroo can go into another kangaroo’s pocket if and only if the size of kangaroo who hold the kangaroo is at least twice as large as the size of kangaroo who is held.

Each kangaroo can hold at most one kangaroo, and the kangaroo who is held by another kangaroo cannot hold any kangaroos.

The kangaroo who is held by another kangaroo cannot be visible from outside. Please, find a plan of holding kangaroos with the minimal number of kangaroos who is visible.

Input

The first line contains a single integer — n(1 ≤ n ≤ 5·105). Each of the next n lines contains an integer si — the size of the i-th kangaroo (1 ≤ si ≤ 105).

Output

Output a single integer — the optimal number of visible kangaroos.

Sample Input

Input

8

2

5

7

6

9

8

4

2

Output

5

Input

8

9

1

6

2

6

5

8

3

Output

5

题意:

有n只袋鼠,小袋鼠能装进大袋鼠里面,但大袋鼠的体型要大于或等于小袋鼠的两倍,小袋鼠被装后不能看见外面,求至少能有多少只袋鼠看得见(设为K)。

理解:

二分做法:

n-k只袋鼠看不见,则外形最小的n-k只袋鼠会被外形最大的n-k只大袋鼠装在口袋里。

贪心:

对n只袋鼠,平均分成两部分,则最优情况是前一半的袋鼠会被后一半的袋鼠装在口袋里。对每一步,最优做法是最后一只袋鼠装住中间的袋鼠,依此类推,即为最优

下面贴代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
int a[500100];
using namespace std;

int select(int key, int n)
{
int temp = n-1;
int flag;
for(int i=key; i>=0; i--)
{
if( 2*a[i] <= a[temp])
{
temp--;
flag = 1;
}
else
{
flag=-1;
break;
}
}
return flag;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a));
for(int i=0; i<n; i++) scanf("%d",&a[i]);
sort(a, a+n);
//for(int i=0; i<n; i++) printf("%d ",a[i]);

int low = 0;
int high = (n+1)/2;
while(low <= high)                     //YRNL....error
{
int mid = (low+high) / 2;
if ( select(mid-1, n)== -1)      //fail,reduce
high = mid -1;
else low = mid + 1;
}
if(2*high > n) printf("%d\n",n-high+1);  //yue jie le
else printf("%d\n",n-high);
}
return 0;
}


写题目时莫名卡数据了,看了数据,发现有一种情况二分越界了。原因是我的二分写法是搜到正确答案后继续后退了一位,正常情况会判断后再前进得到正确答案。但是卡的数据类似于1,2,3),4,6,6,10

二分得到正确的被装的袋鼠的最大值应该是3,组合如下(3,10) (2,6) (1,6) ( 4 )

但是二分越界后(1,2,3,4),6,6,10,组合变为:

(4,10) (3,6) (2,6) (1,4)

同样满足二分的条件。。。。。且temp也越过了中界。。。。

因为这个二分写法必定会越界再返回,改其他的值都会导致新的错误,但考虑上面这种情况只需要在输出时判断,并且分别输出就够了。。。。因为能越过正确值且没有返回,那则说明是中间的袋鼠没有被装,即减一即为正确答案

个人小结:

看数据过题实在是不好。。。。为了过数据而改代码,而不是一开始整体把握思路

PS:

代码还有些地方没想清楚,为什么会出错,可能是和我自己的二分写法有关,暂时记下来,等想明白了再改。。。。

发了博客后马上反应过来。。。。为什么要让二分搜索到不正确的答案呢。。。

处理一下边界值,即当n为奇数时的情况,让他查找不到错误值(最中间的值)。。。归根结底是因为考虑low 和high的值的时候出错了

贴修改后的代码

#include <stdio.h>
#include <string.h>
#include <algorithm>
int a[500100];
using namespace std;

int select(int key, int n)
{
int temp = n-1;
int flag;
for(int i=key; i>=0; i--)
{
if( 2*a[i] <= a[temp])
{
temp--;
flag = 1;
}
else
{
flag=-1;
break;
}
}
return flag;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a));
for(int i=0; i<n; i++) scanf("%d",&a[i]);
sort(a, a+n);
//for(int i=0; i<n; i++) printf("%d ",a[i]);
int m = (n+1)/2;
if(n%2!=0) m--;
int low = 0;
int high = m;
while(low <= high)
{
int mid = (low+high) / 2;
if ( select(mid-1, n)== -1)
high = mid -1;
else low = mid + 1;
}
printf("%d\n",n-high);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: