BZOJ3190:[JLOI2013]赛车
Description
这里有一辆赛车比赛正在进行,赛场上一共有N辆车,分别称为个g1,g2……gn。赛道是一条无限长的直线。最初,gi位于距离起跑线前进ki的位置。比赛开始后,车辆gi将会以vi单位每秒的恒定速度行驶。在这个比赛过程中,如果一辆赛车曾经处于领跑位置的话(即没有其他的赛车跑在他的前面),这辆赛车最后就可以得奖,而且比赛过程中不用担心相撞的问题。现在给出所有赛车的起始位置和速度,你的任务就是算出那些赛车将会得奖。
Input
第一行有一个正整数N表示赛车的个数。
接下来一行给出N个整数,按顺序给出N辆赛车的起始位置。
再接下来一行给出N个整数,按顺序给出N辆赛车的恒定速度。
Output
输出包括两行,第一行为获奖的赛车个数。
第二行按从小到大的顺序输出获奖赛车的编号,编号之间用空格隔开,注意最后一个编号后面不要加空格。
Sample Input
4
1 1 0 0
15 16 10 20
1 1 0 0
15 16 10 20
Sample Output
3
1 2 4
1 2 4
HINT
对于100%的数据N<=10000, 0<=ki<=10^9, 0<=vi<=10^9
题解:
设位置为yi,yi=ki+ti*v,将其看作是y关于t的一次函数图像,毫无疑问,T时刻领先的赛车就是t=T时yi最大的函数。
这样,原题就变成了半平面交的模型,解法同BZOJ1007[HNOI2008]水平可见直线。
代码:
1 var 2 i,j,l,r,n,m:longint; 3 k,b,a,s:array[0..10001]of longint; 4 v:array[0..10001]of boolean; 5 flag:boolean; 6 procedure sort(l,r:longint); 7 var 8 i,j,x,x2,y:longint; 9 begin 10 i:=l; j:=r; x:=k[(l+r)div 2]; x2:=b[(l+r)div 2]; 11 repeat 12 while(k[i]<x)or((k[i]=x)and(b[i]<x2))do inc(i); 13 while(x<k[j])or((x=k[j])and(x2<b[j]))do dec(j); 14 if i<=j then 15 begin 16 y:=k[i]; k[i]:=k[j]; k[j]:=y; 17 y:=b[i]; b[i]:=b[j]; b[j]:=y; 18 y:=a[i]; a[i]:=a[j]; a[j]:=y; 19 inc(i); dec(j); 20 end; 21 until i>j; 22 if i<r then sort(i,r); 23 if j>l then sort(l,j); 24 end; 25 begin 26 readln(n); 27 for i:=1 to n do read(b[i]); 28 for i:=1 to n do read(k[i]); 29 for i:=1 to n do a[i]:=i; 30 sort(1,n); 31 r:=1; i:=1; 32 while(i<n)and(k[i]=k[i+1])and(b[i]<>b[i+1])do inc(i); 33 s[1]:=i; inc(i); k[0]:=-1; 34 while i<=n do 35 begin 36 while(r>0)and(k[i]=k[s[r]])and(b[i]<>b[s[r]])do dec(r); 37 if k[i]<>k[s[r]] then 38 begin 39 while(r>0)and((b[i]-b[s[r]])/(k[s[r]]-k[i])<0)do dec(r); 40 while(r>1)and((b[i]-b[s[r]])/(k[s[r]]-k[i])< 41 (b[s[r]]-b[s[r-1]])/(k[s[r-1]]-k[s[r]])) do dec(r); 42 end; 43 inc(r); s[r]:=i; inc(i); 44 end; 45 fillchar(v,sizeof(v),false); 46 writeln(r); 47 for i:=1 to r do v[a[s[i]]]:=true; 48 flag:=false; 49 for i:=1 to n do 50 if v[i] then 51 begin 52 if not flag then 53 begin 54 flag:=true; write(i); 55 end else write(' ',i); 56 end; 57 writeln; 58 end.