您的位置:首页 > 其它

[几何] BZOJ 4814 [Cqoi2017]小Q的草稿

2017-04-21 08:14 323 查看
把三角形拆成三条线段

以每个点为中心 极角排序一发 然后扫描线 set中维护线段 优先级为到中心点的距离 因为三角形不相交 所以大小关系不会变

遇到一个点就查一下最近的线段是不是挡住了 不然就有贡献

其实三角形对于一个点 只有一条边是有用的

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef double ld;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=5005;
const ld PI=acos(-1.0);
const ld eps=1e-8;
inline int sgn(ld a){
if (fabs(a)<eps) return 0;
return a<0?-1:1;
}

struct PP{
ld x,y,ang;
PP(ld x=0,ld y=0):x(x),y(y) { }
ld dis(){ return sqrt(x*x+y*y); }
void get() { ang=atan2(y,x); }
void read(){ int _x,_y; ::read(_x); ::read(_y); x=_x; y=_y; }
friend PP operator + (PP A,PP B){ return PP(A.x+B.x,A.y+B.y); }
friend PP operator - (PP A,PP B){ return PP(A.x-B.x,A.y-B.y); }
friend ld operator * (PP A,PP B){ return A.x*B.y-A.y*B.x; }
friend PP operator * (PP A,ld B) { return PP(A.x*B,A.y*B); }
friend ld dot(PP A,PP B){ return A.x*B.x+A.y*B.y; }
bool operator < (const PP &B) const{
return ang<B.ang;
}
friend PP I(PP a1,PP a2,PP b1,PP b2){
ld t=((b2-b1)*(a1-b1))/((a2-a1)*(b2-b1));
return a1+(a2-a1)*t;
}
};

PP tag;

struct SS{
PP u,v;
SS() {}
SS(PP u,PP v):u(u),v(v) { }
bool operator < (const SS& B) const{
return I(u,v,PP(0,0),tag).dis()<I(B.u,B.v,PP(0,0),tag).dis();
}
}S
;

multiset<SS> Set;
multiset<SS>::iterator it
;

struct event{
int f,idx; ld ang;
event() {}
event(int f,int idx,ld ang):f(f),idx(idx),ang(ang) { }
bool operator < (const event &B) const{
return sgn(ang-B.ang)==0?f>B.f:sgn(ang-B.ang)<0;
}
}ev
; int tot;

int n,m,ans;
PP _p
,p
,_t
[3],t
[3];
int pt,sg;

inline void Solve(){
tot=0;
for (int i=1;i<=sg;i++)
ev[++tot]=event(1,i,S[i].u.ang),ev[++tot]=event(0,i,S[i].v.ang);
sort(p+1,p+pt+1); sort(ev+1,ev+tot+1);
Set.clear();
int ret=0; int j=1;
for (int i=1;i<=pt;i++){
while (j<=tot && (sgn(ev[j].ang-p[i].ang)<0 || (sgn(ev[j].ang-p[i].ang)==0 && ev[j].f))){
if (ev[j].f)
tag=S[ev[j].idx].u,it[ev[j].idx]=Set.insert(S[ev[j].idx]);
else
tag=S[ev[j].idx].v,Set.erase(it[ev[j].idx]);
j++;
}
if (Set.empty()){ ++ret; continue; }
tag=p[i];
ld dis=I((*Set.begin()).u,(*Set.begin()).v,0,tag).dis();
if (sgn(p[i].dis()-dis)<=0)
ret++;
}
ans+=ret;
}

int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=n;i++) _p[i].read();
for (int i=1;i<=m;i++) for (int j=0;j<3;j++) _t[i][j].read();
for (int i=1;i<=n;i++){
pt=sg=0;
for (int j=i+1;j<=n;j++)
(p[++pt]=_p[j]-_p[i]).get();
for (int j=1;j<=m;j++){
for (int k=0;k<3;k++)
t[j][k]=_t[j][k]-_p[i];
ld maxv=0; PP u,v;
for (int k=0;k<3;k++){
ld ang=dot(t[j][k],t[j][(k+1)%3])/t[j][k].dis()/t[j][(k+1)%3].dis();
ang=acos(ang);
if (ang>maxv) maxv=ang,u=t[j][k],v=t[j][(k+1)%3];
}
u.get(); v.get();
if (u.ang>v.ang) swap(u,v);
if (v.ang-u.ang<PI)
S[++sg]=SS(u,v);
else{
PP tmp=I(u,v,PP(0,0),PP(-1.0,0));
S[++sg]=SS(tmp,u),S[sg].u.ang=-PI,S[++sg]=SS(v,tmp),S[sg].v.ang=PI;
}
}
Solve();
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: