给定N辆赛车的起始点及速度,统计哪些赛车曾经处于领跑位置。
考虑把题目搬到S-T图像上,问题就变成了统计在S-T图像上在顶端的直线的序号,于是就可以用半平面交解决,并且只用考虑队首直线。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NON 50005
#define clr(a) (memset((a),0,sizeof(a)))
typedef long long ll;
struct CAR{
int k,v,id;
const bool operator<(const CAR &a)const{return (v!=a.v)?(v<a.v):(k<a.k);}
}car[NON];
int N;
inline int Read(){
//bool b=false;
int x,ch=getchar();
while((ch<'0'||ch>'9')/*&&ch!='-'*/)ch=getchar();
// if(ch=='-')b=true,ch=getchar();
x=ch-'0';
for(ch=getchar();(ch>='0'&&ch<='9');ch=getchar())
x=(x<<3)+(x<<1)+ch-'0';
return x;
}
inline double time(const CAR a,const CAR b){
// printf("Car %d(%2d,%2d) catch Car %d(%2d,%2d) : time %7.4lf\n",a.id,a.k,a.v,b.id,b.k,b.v,((double)b.k-a.k)/(a.v-b.v));
return ((double)b.k-a.k)/(a.v-b.v);
}
int main(){
static CAR Que[NON];
static int Ans[NON];
int i,head,total=0;
N=Read();
for(i=1;i<=N;++i) car[i].k=Read();
for(i=1;i<=N;++i) car[i].v=Read(),car[i].id=i;
std::sort(car+1,car+N+1);
total=1;
for(i=2;i<=N;++i){
if(car[i].v!=car[i-1].v||(car[i].v==car[i-1].v&&car[i].k==car[i-1].k)) ++total;
car[total]=car[i];
}
N=total;
Que[head=1]=car[1],Ans[1]=car[1].id;
for(i=2;i<=N;++i){
while(head&&time(car[i],Que[head])<0) head--;
while(head>1&&time(Que[head],Que[head-1])>time(car[i],Que[head-1])) head--;
Que[++head]=car[i];
Ans[head]=car[i].id;
}
std::sort(Ans+1,Ans+head+1);
printf("%d\n",head);
for(i=1;i<head;++i)
printf("%d ",Ans[i]);
printf("%d",Ans[head]);
return 0;
}
被PE给坑了一下…