POJ 3304(线段与直线相交)

Language:
Segments
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7144   Accepted: 2135

Description

在平面内给 n 条线段,问是否存在一条直线,使得所有线段在这条直线上的投影有公共点.

Input

第一行输入 T 表示数据组数,接下来 T 组数据每组第一行一个整数 n ≤ 100 表示线段数,接下来n 行每行有 x1 y1 x2 y2 表示线段的两个端点 (x1y1) 和 (x2y2)
.

Output

对于每组数据,如果存在这样的直线,输出一行 "Yes!", 否则输出 "No!" . 精度|a - b| < 10-8.

Sample Input

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0

Sample Output

Yes!
Yes!
No!

Source


显然该题可转换为是否存在一条直线与所有线段相交。(如果存在,则通过移动选转,使其过的2个线段的端点)

需要特判2个点如果相同,那么连不成线段,因为最后叉积算出来为0.


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#define eps 1e-8
#define MAXN (200+10)
struct P
{
	long double x,y;
	P(){}
	P(long double _x,long double _y):x(_x),y(_y){}
}a[MAXN*2];
struct V
{
	long double x,y;
	V(){}
	V(long double _x,long double _y):x(_x),y(_y){}
	V(P a,P b):x(b.x-a.x),y(b.y-a.y){}
};
struct S
{
	P A,B;
	S(P _A,P _B):A(_A),B(_B){}
	S(){}
};
double operator*(V a,V b)
{
	return a.x*b.y-b.x*a.y;
}
bool corr(P A,P B,P C,P D)
{
	V AB=V(A,B),AC=V(A,C),AD=V(A,D);
	return ((AC*AB)*(AB*AD)>-eps);
}
bool fabs (double a,double b)
{
	if (abs(a-b)<eps) return 1 ;return 0;
}
bool fabs(P A,P B)
{
	return (fabs(A.x,B.x)&&fabs(A.y,B.y));
}
int t,n;
int main()
{
//	freopen("poj3304.in","r",stdin);
	scanf("%d",&t);
	while (t--)
	{
		cin>>n;
		bool flag=0;
		for (int i=1;i<=2*n;i++) cin>>a[i].x>>a[i].y;
		for (int i=1;i<2*n&&!flag;i++)
		{
			for (int j=i+1;j<=2*n;j++)
			{
				if (fabs(a[i],a[j])) continue;
				S l=S(a[i],a[j]);
				int k;
				for (k=1;k<=n;k++)
				{
					if (!corr(l.A,l.B,a[k*2-1],a[k*2])) break;
				//	cout<<k;
				}
				if (k==n+1) {cout<<"Yes!n"; flag=1;break;}
			}
		}

		if (!flag) cout<<"No!n";


	}
	return 0;
}


POJ 1269(直线的交点)

Language:
Intersecting Lines
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7657   Accepted: 3510

Description

求两条直线相交部分,给出的坐标的范围在 -1000 到 1000 之间且为整数. 

Input

第一行为数据组数 N≤10 
接下来N行,每行为x1y1x2y2x3y3x4y4.表示第一条直线过 (x1,y1) 和 (x2,y2) ,第二条过 (x3,y3) 和 (x4,y4). 保证直线能被确定.

Output

输出 N+2 第一行输出INTERSECTING LINES OUTPUT. 接下来每行输出相交部分 none, line, 或 point x y(保留2位小数). 最后1行输出 "END OF OUTPUT".

Sample Input

5
0 0 4 4 0 4 4 0
5 0 7 6 1 0 2 3
5 0 7 6 3 -6 4 -3
2 0 2 27 1 5 18 5
0 3 4 0 1 2 2 5

Sample Output

INTERSECTING LINES OUTPUT
POINT 2.00 2.00
NONE
LINE
POINT 2.00 5.00
POINT 1.07 2.20
END OF OUTPUT

Source

模板如下:

注意* 表示叉积

这题涉及已知相交,线段跨立求交点

异侧情况:


同侧情况:




#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define eps 1e-8
double sqr(double x) {return x*x;}
struct P
{
	double x,y;
	P(double _x,double _y):x(_x),y(_y){}
	P(){}
	double dis()
	{
		return sqrt(sqr(x)+sqr(y));
	}
};
struct V
{
	double x,y;
	V(double _x,double _y):x(_x),y(_y){}
	V(P a,P b):x(b.x-a.x),y(b.y-a.y){}
	V(){}
	const double dis()
	{
		return sqrt(sqr(x)+sqr(y));
	}
};
P operator+(const P a,const V b)
{
	return P(a.x+b.x,a.y+b.y);
}
V operator*(const double a,const V b)
{
	return V(a*b.x,a*b.y);
}
double operator*(const V a,const V b)
{
	return a.x*b.y-b.x*a.y;
}
P jiao_dian(const V a,V b,const V c,const V CD,const P C)
{
	double d;
	d=b.dis();
	double s1=a*b,s2=b*c;
	double k=s1/(s1+s2);
	return C+k*CD;
}
bool equal(const double a,const double b)
{
	if (abs(a-b)<eps) return 1;return 0;
}
int n;
int main()
{
//s	freopen("poj1269.in","r",stdin);
	cout<<"INTERSECTING LINES OUTPUT"<<endl;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		double x1,y1,x2,y2,x3,y3,x4,y4;
		scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
		P A=P(x1,y1),B=P(x2,y2),C=P(x3,y3),D=P(x4,y4);
		V AB=V(A,B),AC=V(A,C),AD=V(A,D),CD=V(C,D);
		if (equal((AB*CD),0))
		{
			if (equal((AC*AD),0)) cout<<"LINEn";
			else cout<<"NONEn";
		}
		else
		{
			P p=jiao_dian(AC,AB,AD,CD,C);
			cout.setf(ios::fixed);
			cout.precision(2);
			cout<<"POINT "<<p.x<<' '<<p.y<<endl;
		}
	}
	cout<<"END OF OUTPUT"<<endl;
	return 0;
}

CF 254E(从当前向后递推)

E. 宿舍分享
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

一个学期有 n 天.第i天早上Vasya会带 ai kg食物来学校(食物最多放2天,今天和明天).

Vasya 每天吃 v kg 食物.他带来的食物原来够吃,但是Vasya 的 m 个室友会吃他的,编号
1 到 m. 第  j 个室友会在 lj到 rj
天和他一起住且每天吃 fj kg食物.
Vasya 每天可以给同住的人  j  fj kg食物(可以选一些人分).Vasya每一次分食物都要让人吃饱(要不然不厚道).

Vasya 怎样分出最多次食物?

Input

第一行2个整数 n 和 v (1 ≤ n, v ≤ 400).
第2行 n 个整数 a1, a2, ..., an (1 ≤ ai ≤ 400), 

第三行一个整数 m (1 ≤ m ≤ 400). 接下来 m 行每行3个整数.第
 j 行为 lj, rj, fj (1 ≤ lj ≤ rj ≤ n, 1 ≤ fj ≤ 400).

Output

第一行输出最多分出食物次数. 接下来 n 行第一行输出第 天分几次.接下来输出当天分的朋友的编号(任意顺序).若有多解任意输出一种.

Sample test(s)
input
4 1
3 2 5 4
3
1 3 2
1 4 1
3 4 2
output
7
1 2
1 2
3 2 1 3
2 2 3

Dp题,主要推方程。

显然每天从食量最小的贪起。

为了处理食物隔夜问题,多留一维表示昨天剩下的食物。

由于不好求出向前的方程,也不知道终态,所以要从当前向后递推(而非从前面向当前递推,类似矿工食堂的解决方案)


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iostream>
#include<vector>
using namespace std;
#define MAXN (400+10)
#define MAXV (400+10)
#define MAXAi (400+10)
#define MAXM (400+10)
#define TomorrowFood (min(a[i],x))
#define _Next_ [i+1][TomorrowFood]
int n,m,v;
vector <pair< int,int> > man[MAXN]; // ith day jth man eat k food. //pair(j,k)
int a[MAXN]={0};
int f[MAXN][MAXV*2]={0}; // ith day havv j food left last night,->rat
int totlastf[MAXN][MAXV*2]={0}; //昨晚几个人吃
int last[MAXN][MAXV*2]={0};   //昨晚剩多少
int solve(int i,int j)
{
	if (i>2) solve(i-1,last[i][j]); //{ n+1->n n->n-1 ... 2->1 }   1->0
	cout<<totlastf[i][j];
	for (int k=1;k<=totlastf[i][j];k++)
		cout<<' '<<man[i-1][k].second;
	cout<<endl;
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	cin>>n>>v;
	for (int i=1;i<=n;i++){cin>>a[i]; man[i].push_back(make_pair(0,0)); }
	cin>>m;
	for (int i=1;i<=m;i++)
	{
		int l,r,fi; cin>>l>>r>>fi; //fi=food in a man
		for (int j=l;j<=r;j++)
			man[j].push_back(make_pair(fi,i));
	}
	for (int i=1;i<=n;i++) sort(man[i].begin(),man[i].end());

	memset(f,128,sizeof(f));
	f[1][0]=0;

	for (int i=1;i<=n;i++)
	{
		for (int j=0;j<=a[i-1];j++) //昨晚最多留下a[i] food(其它过期)
		{
			int x=j-v+a[i];  //表示昨天剩下的,吃了v,又多了今天的a[i]
			if (x<0) continue; //一定够吃
			if (f[i+1][TomorrowFood]<f[i][j])
			{
				f[i+1][TomorrowFood]=f[i][j];
				totlastf[i+1][TomorrowFood]=0;
				last _Next_ =j;
			}
			for (int k=1;k<man[i].size();k++)
			{
				x-=man[i][k].first;
				if (x<0) break;
				if (f[i+1][TomorrowFood]<f[i][j]+k)
				{
					f[i+1][TomorrowFood]=f[i][j]+k;
					totlastf[i+1][TomorrowFood]=k;
					last _Next_ =j;
				}
			}
		}
	}

	int ans=-1,now;
	for (int j=0;j<=MAXV;j++)
		if (ans<f[n+1][j]) {ans=f[n+1][j]; now=j; }
	cout<<ans<<endl;
	solve(n+1,now);
	return 0;
}

CF 253D(矩阵-4角相等且矩阵权值有上限的矩阵数)

D. 4a矩阵
time limit per test

2 seconds

memory limit per test

256 megabytes

input

input.txt

output

output.txt

有一个 n × m 的矩阵, 行 1 到 n,
列1 to 
m.

4a矩阵定义:

  • 矩阵内最多有 k 个 "a" ;
  • 4个角相等,长宽大于1.

请在给定矩阵中数出有几个子矩阵是4a矩阵.

Input

第一行3个整数n, m, k (2 ≤ n, m ≤ 400; 0 ≤ k ≤ n·m).

接下来为矩阵.

Output

一个整数,表示4a矩阵数.

Sample test(s)
input
3 4 4
aabb
baab
baab
output
2
input
4 5 1
ababa
ccaca
ccacb
cbabc
output
1
Note

第一个样例的解 (2, 2) (3, 3),

(2, 1) 
(3, 4).

这题是状态压缩问题。

用s[i][j]=∑a[1][j]+a[2][j]+..+a[i][j]

那么我们只需要枚举3个量

行的上下,还有列的

显然r列的关系可以由r-1的关系推出。



#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cstdlib>
using namespace std;
#define MAXN (400+10)
#define MAXM (400+10)
int n,m,k;
char a[MAXN][MAXM];
int s[MAXN][MAXM];  //表示s[i][j]=a[1][j]+a[2][j]+..a[i][j]
int c[1<<8];
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);


	memset(s,0,sizeof(s));
	scanf("%d%d%dn",&n,&m,&k);
	for (int i=1;i<=n;i++)
	{
		gets(a[i]+1);
		for (int j=1;j<=m;j++)
		{
			s[i][j]=s[i-1][j]+(a[i][j]=='a');
		}
	}
	long long ans=0;
	/*
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	*/
	;
	for (int i=1;i<n;i++)
	{
		for (int j=i+1;j<=n;j++)
		{
			int l=1,tot=0;
			memset(c,0,sizeof(c));
			for (int r=1;r<=m;r++)
			{
				tot+=s[j][r]-s[i-1][r];
				while (tot>k)
				{
					tot-=s[j][l]-s[i-1][l];
					c[a[i][l]]-=(a[i][l]==a[j][l]);
					l++;
				}
				if (l<r&&a[i][r]==a[j][r]) ans+=c[a[i][r]];
				if (a[i][r]==a[j][r]) c[a[i][r]]++;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

CF 254C(易位构字法)

C. 易位构字法
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

异位构字就是把一个字符串的顺序改变,可以得到另一个字符串.

对字符串 s 和 t ,至少修改 s 多少位,能使 s 和 t 易位构字?如果有很多方法,输出 s 易位后字典序最小的。

Input

两行 st. 长度不超过 105 ,只有大写字母。

Output

第一行输出最小修改次数,第二行输出 s 修改后字典序最小的字符串。

Sample test(s)
input
ABA
CBA
output
1
ABC
input
CDBABC
ADCABD
output
2
ADBADC
Note

 第二个数据,s 可改成: "ADBADC", "ADDABC",
"CDAABD", "CDBAAD", "CDBADA",
"CDDABA", "DDAABC", "DDBAAC".
字典序最小的是 "ADBADC".

直接处理字符串。

program word;
const
   maxn=100000;
var
   s,t:ansistring;//->ansistring
   n,i,j,ans,size,head:longint;
   pass,a1,a2,deln:array['A'..'Z'] of longint;
   add:array[1..26] of char;
   addn:array[1..26] of longint;
   ic:char;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);
   fillchar(a1,sizeof(a1),0);
   fillchar(a2,sizeof(a2),0);
   fillchar(pass,sizeof(pass),0);
   fillchar(deln,sizeof(deln),0);
   readln(s);
   readln(t);
   n:=length(s);
   for i:=1 to n do inc(a1[s[i]]);
   for i:=1 to n do inc(a2[t[i]]);

   size:=0;
   ans:=0;
   for ic:='A' to 'Z' do
      if a2[ic]>a1[ic] then
      begin
         inc(size);
         add[size]:=ic;
         addn[size]:=a2[ic]-a1[ic];
         inc(ans,addn[size]);
      end
      else if a2[ic]<a1[ic] then
      begin
         deln[ic]:=a1[ic]-a2[ic];
      end;

   writeln(ans);
   head:=1;
   for i:=1 to n do
   begin
      inc(pass[s[i]]);
      if deln[s[i]]>0 then
      begin
         if (add[head]<s[i]) or (deln[s[i]]>a1[s[i]]-pass[s[i]]) then
         begin
            dec(deln[s[i]]);
            s[i]:=add[head];
            dec(addn[head]);
            if addn[head]=0 then inc(head);
         end;
      end;
   end;
   writeln(s);
   close(input);
   close(output);
end.

CF 254B(日期)

B. 评委会
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

2013年要举办 n 场比赛,编号1 到 n. 每场比赛需要人准备(在开幕的前 ti 天(不包括开幕当天))

如果准备时间重复,一个人一天只能为一场比赛准备,请问最少需要雇多少人准备?

Input

第一行一个整数 n  (1 ≤ n ≤ 100). 接下来 n 行每行为midipi 和 ti —
开幕的月份,日期,每天需要的人数,准备天数 (1 ≤ mi ≤ 12di ≥ 11 ≤ pi, ti ≤ 100),输入顺序任意,一天可能有同时多场比赛开幕。

非润年,二月28天. 可能需要在2012年某天开始准备.

Output

输出最小人数。

Sample test(s)
input
2
5 23 1 2
3 13 2 3
output
2
input
3
12 9 2 1
12 8 1 3
12 8 2 2
output
3
input
1
1 10 1 13
output
1

直接模拟,注意日期换算。


Program jury;
var
   n,i,j,m,d,p,t,ans:longint;
   month:array[1..12] of longint=(31,28,31,30,31,30,31,31,30,31,30,31);
   a:array[-1000..1000] of longint;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);
   read(n);
   fillchar(a,sizeof(a),0);
   for i:=1 to n do
   begin
      read(m,d,p,t);
      for j:=1 to m-1 do inc(d,month[j]);
      for j:=d-1 downto d-t do
         inc(a[j],p);
   end;
   ans:=0;
   for i:=-1000 to 1000 do
      if ans<a[i] then ans:=a[i];
   writeln(ans);

   close(input);
   close(output);
end.

CF 254A(重复的数)

A. 数字卡片
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

2n张卡片编号为1 .. 2n.卡片数字相同可凑成一对,能否凑完?

Input

第一行1个整数n (1 ≤ n ≤ 3·105).
第二行有2n个整数a1, a2, ..., a2n (1 ≤ ai ≤ 5000)
表示第i张卡片的数字。

Output

如果凑不完,请输出 -1.否则输出 n 行,每行一对对整数,表示第i张卡片与第j张凑成一对。

输出任意方案。

Sample test(s)
input
3
20 30 10 30 20 10
output
4 2
1 5
6 3
input
1
1 2
output
-1

直接用数组记录出现次数,每遇到一对,就扔入解中。

Program Cards;
const
   maxn=300000;
var
   n,i,p,size:longint;
   a:array[1..5000] of longint;
   q1,q2:array[1..maxn] of longint;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);

   read(n);
   fillchar(a,sizeof(a),0);
   size:=1;
   for i:=1 to 2*n do
   begin
      read(p);
      if a[p]>0 then
      begin
         q1[size]:=a[p];q2[size]:=i;
         inc(size);
         a[p]:=0;
      end
      else a[p]:=i;
   end;
   if size<>n+1 then writeln('-1')
   else for i:=1 to n do writeln(q1[i],' ',q2[i]);

   close(input);
   close(output);
end.

CF 253C(找中转行)

C. 光标移动
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

文本编辑器有n行,每行k个字符(显然光标有k+1个位置,标记为1..k+1.

有4个操作:

  • "Up": 光标将向上移1行,列不变。如果上一行字符太少,则光标跑到行末。

  • "Down":
    光标将向下移1行,列不变。如果上一行字符太少,则光标跑到行末。

  • "Right": 光标向右移1格,操作不能在行末进行。

  • "Left":
    光标向左移1格,操作不能在行首进行。

    求出把光标从 (r1, c1) 移向(r2, c2)最小步数.

  • Input

    第一行一个整数 n (1 ≤ n ≤ 100) . 第二行 n个整数a1, a2, ..., an (0 ≤ ai ≤ 105),
    表示每行字符数. 第三行4个整数 r1, c1, r2, c2 (1 ≤ r1, r2 ≤ n, 1 ≤ c1 ≤ ar1 + 1, 1 ≤ c2 ≤ ar2 + 1).

    Output

    输出最小步数

    Sample test(s)
    input
    4
    2 1 6 4
    3 4 4 2
    
    output
    3
    
    input
    4
    10 5 6 4
    1 11 4 2
    
    output
    6
    
    input
    3
    10 1 10
    1 10 1 1
    
    output
    3
    
    Note

    第一组数据若为

    123

    12

    123s567

    1t345

    则最小操作为 "Left", "Down", "Left".

    显然除了直接移(先行后列)外,

    唯一减少操作数的方法便是向中间以外的行数移,以求降低列的移动数。

    一定要注意不是挪到每行直接取abs(行尾-c2)的,因为可能会有往返行尾的路上有更小的,直接取行尾可能拉近它和c2的距离,但是这种操作是不可行的。

    #include<cstdio>
    #include<functional>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define MAXN (10000+100)
    int a[MAXN],n;
    int abs2(int a,int b)
    {
    	if (a<b) return b-a;
    	else return a-b;
    }
    int main()
    {
    	freopen("input.txt","r",stdin);
    	freopen("output.txt","w",stdout);
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int r1,c1,r2,c2;
    	scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
    	int mi=c1,ans=0,tans=1000000000;
    	if (r1<r2)
    	{
    		ans=r2-r1;
    		for (int i=r1+1;i<=r2;i++) mi=min(mi,a[i]+1);
    		tans=min(tans,ans+abs(mi-c2));
    		for (int i=r1-1,cost=2,mii=mi;i>=1;i--,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    		for (int i=r2+1,cost=2,mii=mi;i<=n;i++,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    	}
    	else
    	{
    		ans=r1-r2;
    		for (int i=r1-1;i>=r2;i--) mi=min(mi,a[i]+1);
    		tans=min(tans,ans+abs(mi-c2));
    		for (int i=r2-1,cost=2,mii=mi;i>=1;i--,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    		for (int i=r1+1,cost=2,mii=mi;i<=n;i++,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    	}
    	cout<<tans<<endl;
    	return 0;
    }

    CF 253B(队列上维护2个指针后移)

    B. 实验误差
    time limit per test

    1 second

    memory limit per test

    256 megabytes

    input

    input.txt

    output

    output.txt

    小明做实验,测了n次结果,因为误差,这些结果不一样。

    至少修改多少结果,才能使最大的结果不超过最小的结果的2倍?

    Input

    第一行一个整数 n (2 ≤ n ≤ 105),第二行有n个数c1, c2, ..., cn表示结果(1 ≤ ci ≤ 5000)

    Output

    输出一个整数,表示最小修改次数。

    Sample test(s)
    input
    6
    4 5 3 8 3 7
    
    output
    2
    
    input
    4
    4 3 2 4
    
    output
    0
    
    Note

    第1个数据删除8,7,第二个数据本身就满足条件。

    排序,从小到大枚举最小数,并把后指针挪向最大的不用修改的数进行统计即可。


    #include<cstdio>
    #include<functional>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define MAXN (100000+100)
    int a[MAXN];
    int n;
    int main()
    {
    	freopen("input.txt","r",stdin);
    	freopen("output.txt","w",stdout);
    
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	a[n+1]=1000000;
    //	for (int i=1;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
    	int t=1,ans=0;
    	for (int h=1;h<=n;h++)
    	{
    		while (a[h]*2>=a[t+1]) t++;
    		ans=max(ans,t-h+1);
    	}
    	cout<<n-ans<<endl;
    
    }
    



    CF 253A(最大间隔相异队列)

    A. 男孩女孩
    time limit per test

    1 second

    memory limit per test

    256 megabytes

    input

    input.txt

    output

    output.txt

    有n个男孩和m个女孩排队,我们希望相邻的2个孩子性别尽可能不同。

    请帮助它们排队。

    Input

    第1行有2个整数 n,m (1 ≤ n, m ≤ 100).

    Output

    请输出一行它们排队的队列,B表示男孩,G表示女孩.

    输出任意一种方案即可。

    Sample test(s)
    input
    3 3
    
    output
    GBGBGB
    
    input
    4 2
    
    output
    BGBGBB
    
    Note

    In the first sample another possible answer is BGBGBG.

    In the second sample answer BBGBGB is also optimal.

    分成2种情况考虑-男多女少和女多男少

    考虑以下2种情况:

    BGBGBB

    BGBGGG-->GBGBGG 显然后面间隔较多


    Program Boys;
    var
       n,m,i:longint;
    begin
       assign(input,'input.txt');
       assign(output,'output.txt');
       reset(input);
       rewrite(output);
       read(n,m);
       if n<m then
       begin
          for i:=1 to n do write('GB');
          for i:=n+1 to m do write('G');
       end
       else
       begin
          for i:=1 to m do write('BG');
          for i:=m+1 to n do write('B');
       end;
       writeln;
    
       close(input);close(output);
    end.