题目链接:[JLOI2013]赛车
对每个赛车列出他的x-t函数画在二维坐标系中,发现其实就是水平可见直线那道题了
我们将函数按照第一维v从小到大,第二维起始位置从大到小排序,然后对于有序的三发函数a,b,c,如果b,c的交点在a,b的左边b就不会成为领跑的了
最后要把交点在第二象限的函数删去
注意数据中有v全是0的情况QAQ
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
int n,sta[maxn],id[maxn],ans[maxn];
struct Car{int st,v,id;}c[maxn];
int top=0,cnt=0;
bool flag[maxn];
bool cmp(const Car &a,const Car &b){
return a.v<b.v||(a.v==b.v&&a.st>b.st);
}
double getx(int x,int y){
if (c[y].v-c[x].v==0) return 1e10;
return (double)((double)c[x].st-c[y].st)/(double)(c[y].v-c[x].v);
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&c[i].st);
for (int i=1;i<=n;++i) scanf("%d",&c[i].v);
for (int i=1;i<=n;++i) c[i].id=i;
sort(c+1,c+n+1,cmp);
sta[++top]=1; id[top]=c[1].id;
for (int i=2;i<=n;++i){
if (c[i].v==c[i-1].v&&c[i].st<c[i-1].st) continue;
while (top>1&&getx(sta[top-1],sta[top])>getx(sta[top],i)) top--;
sta[++top]=i; id[top]=c[i].id;
}
for (int i=2;i<=top;++i)
if (getx(sta[i-1],sta[i])<0) flag[i-1]=1;
for (int i=1;i<=top;++i)
if (!flag[i]) ans[++cnt]=id[i];
sort(ans+1,ans+cnt+1);
printf("%d\n",cnt);
for (int i=1;i<cnt;++i) printf("%d ",ans[i]);
if (cnt) printf("%d",ans[cnt]);
}