QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#48822 | #4515. Triangles | ShanLunjiaJian | 50 ✓ | 1086ms | 21700kb | C++17 | 4.1kb | 2022-09-16 10:13:20 | 2022-09-16 11:55:31 |
Judging History
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)