分析:
在任一时刻
t
t
,赛车的位置为:
gi+vit
g
i
+
v
i
t
我们可以得到若干形如上式的方程,对于每一辆赛车,询问是否存在一
t
t
使得最大
一次函数形式,如果我们把这些式子画到二维平面上,就得到若干直线
青色(淡蓝色,水蓝色,管你什么蓝色)的线标出来的就是获奖赛车
显然,我们只需要把这
n
n
条直线求一个半平面交,半平面上的点在哪条直线上,哪辆赛车就可以获奖
我一开始naive求一个半平面交,之后暴力判断点是否在直线上
赤裸裸的T啊
我们把直线按照排序,(
v
v
相同的直线,大的排名靠前)把这些直线都扔到一个单调栈里
我们每次插入一条直线,那么什么样的直线才是合法的呢(出栈条件是什么)?
现在栈里已经有了红线和橙线
如果插入蓝线,我们发现ta和
S[top]
S
[
t
o
p
]
的交点较靠上,直接入栈即可
如果插入绿线,我们发现ta和
S[top]
S
[
t
o
p
]
的交点较靠下,所以我们要把
S[top]
S
[
t
o
p
]
弹出,再插入绿线
也就是说我们可以通过和栈顶两条直线的交点位置判断是否要弹栈
但是平行直线是没有办法求交点的
然而因为我们在相同斜率的情况下优先插入b值大的直线
所以如果遇到斜率相同的直线直接忽略即可
在最后统计答案的时候,如果两条直线重合,那么这两辆赛车都可以获奖
还有一个小细节:
我们在最后维护答案的时候,有可能出现
S[1]
S
[
1
]
和
S[2]
S
[
2
]
这样的情况
也就是说,如果平面包括第二象限,那么这两条直线是合法的
但是我们的图像只能在第一和第四象限
因此我们在最后需要特殊判断一下:栈中相邻的两条直线的交点横坐标是否大于零
tip
不懂,人懒不想改
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-7;
const int N=10010;
struct node{
double k,b;
int id,num;
bool operator <(const node &a) const{
return (k<a.k)||(k==a.k&&b>a.b);
}
};
node l[N],S[N];
int n,m,top=0,ans[N];
bool vis[N];
int dcmp(double x) {
if (fabs(x)<eps) return 0;
else if (x>0) return 1;
else return -1;
}
double jiao(node l1,node l2) {
return (l2.b-l1.b)/(l1.k-l2.k);
}
int check(node l1,node l2,node L) {
double x=jiao(l1,l2);
double t1=l1.k*x+l1.b;
double t2=l2.k*x+l2.b;
return dcmp(t1-t2)<0;
}
void solve() {
for (int i=1;i<=n;i++) {
if (top&&dcmp(l[i].k-S[top].k)==0) continue;
//斜率相同的情况下我们插入的是b最大的直线
while (top>1&&check(S[top],S[top-1],l[i])) top--;
S[++top]=l[i];
}
for (int i=1;i<=top;i++) {
if (i!=top) {
double x=jiao(S[i],S[i+1]);
if (dcmp(x)<0) continue;
//交点横坐标必须为正
}
node now=S[i];
for (int i=now.num;i<=n;i++)
if (dcmp(now.k-l[i].k)==0&&dcmp(now.b-l[i].b)==0) //平行直线都可以获胜
vis[l[i].id]=1;
else break;
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf",&l[i].b),l[i].id=i;
for (int i=1;i<=n;i++) scanf("%lf",&l[i].k);
sort(l+1,l+1+n);
for (int i=1;i<=n;i++) l[i].num=i;
solve();
for (int i=1;i<=n;i++)
if (vis[i]) ans[++ans[0]]=i;
printf("%d\n",ans[0]);
for (int i=1;i<=ans[0];i++)
printf("%d%c",ans[i],i==ans[0]? '\n':' ');
return 0;
}