传送门:bzoj3190
题解
半平面交板题。
写半平面需要记住下面两张图:
加入一条边时首尾都可能更新。
需要把末尾多余的删除。
p.s.需要特判只与半平面交一个点和重合的线。
好卡精度啊。
代码
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define db double
using namespace std;
const db eps=1e-10;
const int N=1e4+2;
int n,bs[N],tot=1,ans[N];
struct P{
db x,y;
};
struct L{
int k,slop;
int tag;
bool operator <(const L& u)const{
if(slop==u.slop)
return k<u.k;
return slop<u.slop;
}
}t[N];
inline db inter(L a,L b)
{
return (db)(b.k-a.k)/(a.slop-b.slop);
}
void work()
{
for(int i=2;i<=n;i++){
if(t[i].slop!=t[i-1].slop) tot++;
else if(t[i].slop==t[i-1].slop && t[i].k==t[i-1].k) tot++;
t[tot]=t[i];
}n=tot;tot=1;
bs[tot]=1;ans[1]=t[1].tag;
for(int i=2;i<=n;i++){
while(tot&&inter(t[i],t[bs[tot]])<-eps) tot--;
while(tot>1&&(inter(t[bs[tot-1]],t[bs[tot]])>inter(t[i],t[bs[tot-1]])))
tot--;
bs[++tot]=i;ans[tot]=t[i].tag;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&t[i].k);
for(int i=1;i<=n;i++) scanf("%d",&t[i].slop);
for(int i=1;i<=n;i++) t[i].tag=i;
sort(t+1,t+n+1);
work();
printf("%d\n",tot);
sort(ans+1,ans+tot+1);
for(int i=1;i<=tot;i++){
if(tot==i) printf("%d",ans[i]);
else printf("%d ",ans[i]);
}
return 0;
}
这个WA了(大概是精度被卡了TAT
#include<bits/stdc++.h>
#define sqr(x) (x*x)
typedef long double db;
using namespace std;
const db eps=1e-10;
const int N=10010;
int n,m,stk[N],hd,tl,ans[N];
char cp;
inline int rd()
{
int x=0,f=1;cp=getchar();
for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=-1;
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
return x*f;
}
struct P{
db x,y;
P(db x_=0,db y_=0):x(x_),y(y_){};
inline P operator +(const P&ky){return P(x+ky.x,y+ky.y);}
inline P operator -(const P&ky){return P(x-ky.x,y-ky.y);}
inline db operator ^(const P&ky){return x*ky.y-y*ky.x;}
inline P operator *(const db&ky){return P(x*ky,y*ky);}
inline P operator /(const db&ky){return P(x/ky,y/ky);}
inline db sq(){return sqr(x)+sqr(y);}
bool operator <(const P&ky)const{
db a=atan2(y,x),b=atan2(ky.y,ky.x);
return a!=b?a<b:x<ky.x;
}
}p[N];
struct Line{
P st,ed,dir;int id;
Line(){};
Line(P st_,P ed_){st=st_;ed=ed_;dir=ed-st;}
}le[N];
inline int dcmp(db x){if(fabs(x)<eps) return 0;return x>0?1:-1;}
inline bool onlf(P a,P b,P c){return (dcmp((c-b)^(b-a))>-1);}
inline bool cmp(Line a,Line b)
{
if(a.dir.y==0 && b.dir.y==0) return a.dir.x<b.dir.x;
if((a.dir.y<=0 && b.dir.y<=0)||(a.dir.y>0 && b.dir.y>0)){
int re=dcmp(a.dir^b.dir);
return (!re)?onlf(b.st,a.st,b.ed):re>0;
}
return a.dir.y<b.dir.y;
}
inline P inter(Line a,Line b)
{
db sa=a.dir^b.dir,sb=b.dir^(a.st-b.st);
return a.st+(a.dir*sb/sa);
}
inline void hpi()
{
int i;sort(le+1,le+n+1,cmp);
for(i=1;i<=n;++i)
if((!m)||(dcmp(le[i].dir^le[i-1].dir))||((!dcmp(le[i].dir.y-le[i-1].dir.y)) && (!dcmp(le[i].st.y-le[i-1].st.y)))) le[++m]=le[i];
n=m;stk[(hd=tl=1)]=1;
for(i=2;i<=n;++i){
for(;hd<tl && (!onlf(le[i].st,p[tl-1],le[i].ed));--tl);
for(;hd<tl && (!onlf(le[i].st,p[hd],le[i].ed));++hd);
stk[++tl]=i;
if(hd<tl) p[tl-1]=inter(le[i],le[stk[tl-1]]);
}
for(;hd<tl && (!onlf(le[stk[hd]].st,p[tl-1],le[stk[hd]].ed));--tl);
for(;hd<tl && p[hd].x<-eps;++hd);
}
int main(){
int i;n=rd();
for(i=1;i<=n;++i) le[i].st.y=rd();
for(i=1;i<=n;++i)
le[i].dir.x=1,le[i].id=i,le[i].dir.y=rd();
for(i=1;i<=n;++i) le[i].ed=le[i].st+le[i].dir;
hpi();printf("%d\n",tl-hd+1);
for(i=hd;i<=tl;++i) ans[i]=le[stk[i]].id;
sort(ans+hd,ans+tl+1);
for(i=hd;i<=tl;++i) printf("%d ",ans[i]);
return 0;
}