QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#48822#4515. TrianglesShanLunjiaJian50 ✓1086ms21700kbC++174.1kb2022-09-16 10:13:202022-09-16 11:55:31

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-09-16 11:55:31]
  • 评测
  • 测评结果:50
  • 用时:1086ms
  • 内存:21700kb
  • [2022-09-16 10:13:20]
  • 提交

answer

#include<stdio.h>
#include<vector>
#include<algorithm>
using std::min_element;
using std::vector;

int n;

struct P{ int x,y,id; inline bool operator < (P b) const { return x==b.x?y<b.y:x<b.x; } };
vector<P> p;
struct T{ P a,b,c; };
vector<T> t;

inline long long cross(P a,P b,P c){ return (long long)(b.x-a.x)*(c.y-a.y)-(long long)(b.y-a.y)*(c.x-a.x); }
inline long long dot(P a,P b,P c){ return (long long)(b.x-a.x)*c.x+(long long)(b.y-a.y)*c.y; }

inline int min(int x,int y){ return x<y?x:y; }
inline int max(int x,int y){ return x>y?x:y; }
inline int sgn(int x){ return x>0?1:-(x<0); }
inline bool seg_cross(P a1,P b1,P a2,P b2)
{
	if(!cross(a1,b1,a2)||!cross(a1,b1,b2)||!cross(a2,b2,a1)||!cross(a2,b2,b1)) return !cross(a1,b1,a2)&&!cross(a1,b1,b2)&&sgn(max(min(a1.x,b1.x),min(a2.x,b2.x))-min(max(a1.x,b1.x),max(a2.x,b2.x)))+sgn(max(min(a1.y,b1.y),min(a2.y,b2.y))-min(max(a1.y,b1.y),max(a2.y,b2.y)))<0;
	return (cross(a1,b1,a2)>0)!=(cross(a1,b1,b2)>0)&&(cross(a2,b2,a1)>0)!=(cross(a2,b2,b1)>0);
}
inline bool check(T a,T b){ return seg_cross(a.a,a.b,b.a,b.b)||seg_cross(a.b,a.c,b.a,b.b)||seg_cross(a.a,a.c,b.a,b.b)||seg_cross(a.a,a.b,b.b,b.c)||seg_cross(a.b,a.c,b.b,b.c)||seg_cross(a.a,a.c,b.b,b.c)||seg_cross(a.a,a.b,b.a,b.c)||seg_cross(a.b,a.c,b.a,b.c)||seg_cross(a.a,a.c,b.a,b.c); }

inline long long dist2(P a,P b){ return (long long)(a.x-b.x)*(a.x-b.x)+(long long)(a.y-b.y)*(a.y-b.y); }

inline void reduce(vector<P> &in,vector<P> &out)
{
	P u=*in.begin(),v=*++in.begin();
	auto cmp1=[=](P a,P b){ return cross(v,a,b)?cross(v,a,b)>0:dist2(v,a)<dist2(v,b); };
	auto cmp2=[=](P a,P b){ return cross(v,a,b)?cross(v,a,b)<0:dist2(v,a)<dist2(v,b); };
	auto w1=min_element(out.begin(),out.end(),cmp1),w2=min_element(out.begin(),out.end(),cmp2),w=out.end();
	if(cross(u,v,*w1)<0) w=w1;
	else if(cross(u,v,*w2)>0) w=w2;
	t.push_back({u,v,*w}),in.erase(in.begin()),in.erase(in.begin()),out.erase(w);
}

inline void solve(vector<P> p)
{
	if(p.size()<3) return;
	P u=*p.begin(),v=*++p.begin();
	auto cmp1=[=](P a,P b){ return cross(v,a,b)?cross(v,a,b)>0:a.x<b.x; };
	auto cmp2=[=](P a,P b){ return cross(v,a,b)?cross(v,a,b)<0:a.x<b.x; };
	auto w1=min_element(p.begin()+2,p.end(),cmp1),w2=min_element(p.begin()+2,p.end(),cmp2),w=p.end();
	if(cross(u,v,*w1)<0) w=w1;
	else if(cross(u,v,*w2)>0) w=w2;
	else
	{
		while(n%3) p.pop_back(),n--;
		int c=p.size();
		while(!t.empty()&&3*c>2*p.size())
		{
			T i=*--t.end();
			p.push_back(i.a),p.push_back(i.b),p.push_back(i.c);
			c+=(cross(u,v,i.a)==0)+(cross(u,v,i.b)==0)+(cross(u,v,i.c)==0);
			t.pop_back();
		}
		vector<P> on,above,below;
		for(P i:p)
			if(cross(u,v,i)==0) on.push_back(i);
			else if(cross(u,v,i)>0) above.push_back(i);
			else below.push_back(i);
		while(on.size()>2*(above.size()+below.size())) on.pop_back();
		auto cmp3=[=](P a,P b){ return dot(u,v,a)<dot(u,v,b); };
		sort(on.begin(),on.end(),cmp3);
		if(on.size()==2*(above.size()+below.size()))
		{
			while(above.size()) reduce(on,above);
			while(below.size()) reduce(on,below);
		}
		else
		{
			while(on.size()>3&&above.size()) reduce(on,above);
			while(on.size()>3&&below.size()) reduce(on,below);
			vector<P> v;
			for(P i:on) v.push_back(i);
			for(P i:above) v.push_back(i);
			for(P i:below) v.push_back(i);
			bool flag=0;
			for(int i=0,j=i+1;j<6&&!flag;j++)
				for(int k=j+1;k<6&&!flag;k++)
				{
					bool b[6]={0};
					b[i]=1,b[j]=1,b[k]=1;
					int l=0,m=0,n=0;
					while(b[l]) l++;
					b[l]=1;
					while(b[m]) m++;
					b[m]=1;
					while(b[n]) n++;
					b[n]=1;
					if(cross(v[i],v[j],v[k])&&cross(v[l],v[m],v[n])&&!check({v[i],v[j],v[k]},{v[l],v[m],v[n]})) t.push_back({v[i],v[j],v[k]}),t.push_back({v[l],v[m],v[n]}),flag=1;
				}
		}
		return;
	}
	t.push_back({u,v,*w}),p.erase(w),p.erase(p.begin()),p.erase(p.begin()),solve(p);
}

int main()
{
	int _T;
	scanf("%d",&_T);
	for(int __T=1;__T<=_T;__T++)
	{
		t.clear(),p.clear();
		scanf("%d",&n);
		for(int i=1,x,y;i<=n;i++) scanf("%d%d",&x,&y),p.push_back({x,y,i});
		sort(p.begin(),p.end()),solve(p);
		printf("Case #%d: %d\n",__T,t.size());
		for(T i:t) printf("%d %d %d\n",i.a.id,i.b.id,i.c.id);
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 8
Accepted
time: 3ms
memory: 3164kb

input:

100
10
220238472 224691753
770968360 1070897
222060078 225731229
213423928 -699125511
571809960 -531790999
-29325160 82281481
523892900 397968241
134123366 175551277
-48116654 71558357
79192162 144205493
6
-800120306 681957950
-800120120 681958048
-800120239 681957972
-800120068 681958102
-800120280...

output:

Case #1: 3
9 6 4
10 8 5
1 3 2
Case #2: 2
1 5 3
6 2 4
Case #3: 4
11 7 12
4 8 3
6 10 9
1 2 5
Case #4: 0
Case #5: 2
6 1 4
2 3 5
Case #6: 3
1 7 4
9 5 2
8 3 6
Case #7: 2
7 3 1
5 2 4
Case #8: 3
2 7 1
10 6 9
3 4 8
Case #9: 4
11 3 9
4 5 2
12 6 10
8 7 1
Case #10: 2
4 5 1
3 6 2
Case #11: 4
11 8 5
9 10 12
1 4 ...

result:

ok  (100 test cases)

Test #2:

score: 42
Accepted
time: 1086ms
memory: 21700kb

input:

100
3000
-92089322 -224238223
-92147554 -225776486
-91601000 -225100640
-92024176 -225644144
-90703509 -224917680
-89202055 -225283952
-92681755 -224149407
-92347180 -225441739
-92259568 -225588653
-91979455 -224254694
-92673281 -224244242
-92527577 -224172521
-90804449 -224883170
-92641474 -2249482...

output:

Case #1: 1000
2743 436 1593
169 2938 1759
2812 2792 2457
46 624 2409
2863 424 999
1335 2697 238
311 2919 1095
1332 787 1523
1515 1042 534
1830 2114 1336
2496 916 275
2666 2023 1297
1693 2685 2234
589 2755 1087
1182 533 2173
2993 2386 2184
1185 1958 2878
2232 2584 764
235 1570 2911
747 2850 1713
57 2...

result:

ok  (100 test cases)