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

Sample Output

3
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.
View Code
posted @ 2017-01-08 18:29  GhoStreach  阅读(203)  评论(0编辑  收藏  举报