[CQOI2017]小Q的草稿

传送门

把三角形拆成三条线段,以每个点为中心,极角排序,扫描线,用set维护线段,优先级为到中心点的距离,三角形不相交,相对顺序不变 ,查一下最近的线段是否挡住了,否则有贡献。

三角形的三条边实际上只有一条边有用。

#include
#define il inline
#define rint register int
using namespace std;
typedef double db;
const int N=5005;
const db PI=acos(-1.0),eps=1e-8;
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
il int read() {
	rint x=0;
	char c=getchar();
	for(; !isdigit(c); c=getchar());
	for(; isdigit(c); c=getchar()) x=(x+(x<<2)<<1)+c-48;
	return x;
}
il int sgn(db a) {
	if(fabs(a) s;
multiset::iterator it[N];
struct E {
	int f,idx;
	db ag;
	E() {} E(int f,int idx,db ag):f(f),idx(idx),ag(ag) {}
	bool operator <(const E &B) const {
		return sgn(ag-B.ag)==0?f>B.f:sgn(ag-B.ag)<0;
	}
} ev[N];
il void Solve() {
	tot=0;
	for(rint i=1; i<=sg; ++i) ev[++tot]=E(1,i,S[i].u.ag),ev[++tot]=E(0,i,S[i].v.ag);
	sort(p+1,p+pt+1);
	sort(ev+1,ev+tot+1);
	s.clear();
	rint ret=0,j=1;
	for(rint i=1; i<=pt; ++i) {
		while(j<=tot &&(sgn(ev[j].ag-p[i].ag)<0 ||(sgn(ev[j].ag-p[i].ag)==0 && ev[j].f))) {
			if(ev[j].f) tt=S[ev[j].idx].u,it[ev[j].idx]=s.insert(S[ev[j].idx]);
			else tt=S[ev[j].idx].v,s.erase(it[ev[j].idx]);
			++j;
		}
		if(s.empty()) {
			++ret;
			continue;
		}
		tt=p[i];
		db dis=I((*s.begin()).u,(*s.begin()).v,0,tt).dis();
		if(sgn(p[i].dis()-dis)<=0) ++ret;
	}
	ans+=ret;
}
int main() {
	n=read(),m=read();
	for(rint i=1; i<=n; ++i) _p[i].Read();
	for(rint i=1; i<=m; ++i) for(rint j=0; j<3; ++j) _t[i][j].Read();
	for(rint i=1; i<=n; ++i) {
		pt=sg=0;
		for(rint j=i+1; j<=n; ++j) (p[++pt]=_p[j]-_p[i]).get();
		for(rint j=1; j<=m; ++j) {
			for(rint k=0; k<3; ++k) t[j][k]=_t[j][k]-_p[i];
			db ma=0;
			P u,v;
			for(rint k=0; k<3; ++k) {
				db ag=dot(t[j][k],t[j][(k+1)%3])/t[j][k].dis()/t[j][(k+1)%3].dis();
				ag=acos(ag);
				if(ag>ma) ma=ag,u=t[j][k],v=t[j][(k+1)%3];
			}
			u.get();
			v.get();
			if(u.ag>v.ag) swap(u,v);
			if(v.ag-u.ag

你可能感兴趣的:(扫描线)