[几何] UR #16 B.破坏蛋糕

详见官方题解


#include<cstdio>
#include<cstdlib>  
#include<algorithm>  
#include<cmath>  
#include<iostream>
#include<set>
#define dprintf(...) fprintf(stderr,__VA_ARGS__)
using namespace std; 
typedef long long ll; 
typedef long double ld;

const ld PI=acosl(-1.0);
const ld eps=1e-13;
   
inline char nc(){  
    static char buf[100000],*p1=buf,*p2=buf;  
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  
    return *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=100005;  
   
inline double sqr(int x){ return (double)x*x; }  
   
struct Point{  
    ld x,y;  
    Point(ld x=0,ld y=0):x(x),y(y) { }  
    friend bool operator < (const Point A,const Point B) { return A.x==B.x?A.y<B.y:A.x<B.x; }
    friend ld operator * (Point A,Point B){ return A.x*B.y-A.y*B.x; }
	friend Point operator * (Point A,ld x){ return Point(A.x*x,A.y*x); }  
    friend Point operator - (Point A,Point B){ return Point(A.x-B.x,A.y-B.y); } 
    friend Point operator + (Point A,Point B){ return Point(A.x+B.x,A.y+B.y); }  
    friend double dist(Point A,Point B){ return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y)); }  
};

typedef pair<Point,int> abcd;
abcd P[N];

struct Line{
	Point p,v;
	Line() { }
	Line(Point a,Point b):p(a),v(b-a) { }
	void read() {
		int x1,x2,y1,y2; ::read(x1),::read(y1),::read(x2),::read(y2);
		*this=Line(Point((double)x1,(double)y1),Point((double)x2,(double)y2));
	}
	void rev(){ p=p+v; v=Point(-v.x,-v.y); }
	ld Tan(){ return atan2l(v.y,v.x); }
	friend Point Cross(Line A,Line B){ return B.p+B.v*((B.p-A.p)*A.v/(A.v*B.v)); }
}L[N],l;

int n;
ld a[N];

multiset<ld> Set;
typedef multiset<ld>::iterator ITER;
int cnt;

int check(ld a,ld b,int f=0){
	if (a==b && f) return 1;
	if (a>b) a-=PI*2;
	return b-a>PI-eps;
}
inline void Ins(ld c){
	ITER pre,next,it; int fp=0,fn=0;
	pre=next=it=Set.insert(c);
	if (pre==Set.begin()) pre=--Set.end(),fp=1; else pre--;
	if (++next==Set.end()) next=Set.begin(),fn=1;
	cnt+=check(*pre,*it,fp)+check(*it,*next,fn)-check(*pre,*next,fp||fn);
}
inline void Del(ld c){
	ITER pre,next,it; int fp=0,fn=0;
	pre=next=it=Set.find(c);
	if (pre==Set.begin()) pre=--Set.end(),fp=1; else pre--;
	if (++next==Set.end()) next=Set.begin(),fn=1;
	cnt-=check(*pre,*it,fp)+check(*it,*next,fn)-check(*pre,*next,fp||fn);
	Set.erase(it);
}

int main(){
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n);
	for (int i=1;i<=n;i++) L[i].read();
	l.read();
	for (int i=1;i<=n;i++){
		if (l.v*L[i].v<0) L[i].rev();
		Ins(a[i]=L[i].Tan());
		P[i]=abcd(Cross(L[i],l),i);
	}
	sort(P+1,P+n+1);
	ITER it1,it2;
	cnt=check(*--Set.end(),*Set.begin(),1);
	for(ITER it1=Set.begin(),it2=++Set.begin();it2!=Set.end();it1++,it2++)
		cnt+=check(*it1,*it2);
	for(int i=1;i<=n;i++)
	{
		cnt?putchar('0'):putchar('1');
		int idx=P[i].second;
		Del(a[idx]);
		a[idx]+=PI;
		if(a[idx]>PI) a[idx]-=2*PI;
		Ins(a[idx]);
	}
	cnt?putchar('0'):putchar('1');
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值