列表

详情


NC50897. Polygons

描述

Lines make polygons. Given N lines, please tell how many closed polygons are formed by these N straight lines and what is the largest and smallest area of them? Moreover, could you tell q_i-th largest area?

输入描述

The first line of input contains an integers N indicating the number of lines.
Following N lines each contains four space-separated integers x_1, y_1, x_2, y_2 indicating two points on the i-th line.
The next line contains an integer M indicating the number of questions.
Following M lines each contains an integer q_i.





No three lines intersect in one point
No two lines coincide
There is at least 1 closed polygon

输出描述

First output a single line containing three numbers, the number of closed polygons, the largest area and the smallest area.
Then, output m lines each contains a number indicating q_i-th largest area.
If q_i is greater than the number of polygons, output (without quotes) instead.
Your answer will be considered correct if its absolute or relative error doesn't exceed

示例1

输入:

6
1 1 0 2
1 3 0 4
1 6 0 7
1 3 0 2
1 -1 0 -2
1 4 0 4
7
1
2
3
4
5
6
7

输出:

6 5.75 0.25
5.75
4.0
3.0
2.25
1.0
0.25
Invalid question

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 738ms, 内存消耗: 118392K, 提交时间: 2022-06-18 19:40:07

/*
Author: fffasttime
Date: 2019/07/27 21:00
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inc(i,n) for (int i=0;i<n;i++)
const int N=1010;
typedef double db;
const db eps=1e-10;
bool eq(db x){return fabs(x)<eps;}
struct vec{
	db x,y;
	vec operator-(const vec &v)const{return {x-v.x,y-v.y};}
	vec operator+(const vec &v)const{return {x+v.x,y+v.y};}
	vec operator*(db t)const{return {x*t,y*t};}
	bool operator<(const vec &v) const{return eq(x-v.x)?y<v.y:x<v.x;}
	db operator&(const vec &v)const{return x*v.y-y*v.x;}
	void rd(){scanf("%lf%lf",&x,&y);}
	//void rd(){x=rand()%1000; y=rand()%1000;}
	db ang()const{return atan2(y,x);}
}p[N*N*2],l1[N],l2[N];//p[n..n+2q] used for question

const db pi=acos(-1);

struct Edge{ //main transfer structure
	db ang; int u,v,w; bool vis;
	int rk;
	int fr;
	Edge(){}
	Edge(int u, int v, int w):u(u),v(v){
		ang=(p[v]-p[u]).ang();
		rk=fr=0;
		vis=0;
	}
	bool operator<(const Edge &v)const{return ang<v.ang;}
}ed[N*N*4];
int edc=1,gcnt=0;

vector<int> ed1[N*N];
vector<int> linep[N];
db ans[N*N*2]; int ansc;
vec lineInt(vec p, vec vp, vec q, vec vq){
	db t=(vq & p-q)/(vp&vq);
	return p+vp*t;
}
int main(){
	int n0; scanf("%d",&n0);
	int n=0;
	inc(i,n0){
		l1[i].rd(); l2[i].rd();
		inc(j,i) if (!eq((l2[i]-l1[i]&l2[j]-l1[j]))){
			p[n]=lineInt(l1[i],l2[i]-l1[i],l1[j],l2[j]-l1[j]);
			linep[i].push_back(n);
			linep[j].push_back(n);
			n++;
		}
	}
	inc(i,n0){
		sort(linep[i].begin(),linep[i].end(),[&](int x, int y){return p[x]<p[y];});
		for (int j=0;j<linep[i].size()-1;j++){
			int x=linep[i][j], y=linep[i][j+1];
			ed[++edc]=Edge(x,y,0);
			ed1[x].push_back(edc);
			ed[++edc]=Edge(y,x,0);
			ed1[y].push_back(edc);
		}
	}
	inc(i,n){
		sort(ed1[i].begin(),ed1[i].end(),[&](int a, int b){return ed[a].ang<ed[b].ang;});
		inc(j,ed1[i].size())
			ed[ed1[i][j]].rk=j;
	}
	int gout;
	for (int i=2;i<=edc;i++) if(!ed[i].vis){ //new
		int u=ed[i].u; int cur=i;
		gcnt++;
		db area=0;
		while (!ed[cur].vis){ //face
			ed[cur].fr=gcnt;
			ed[cur].vis=1;
			area+=(p[ed[cur].u]-p[u])&(p[ed[cur].v]-p[u]);
			int sz=ed1[ed[cur].v].size();
			int rk1=(ed[cur^1].rk-1+sz)%sz;
			cur=ed1[ed[cur].v][rk1];
		}
		if (area<=0) gout=gcnt;
		else ans[ansc++]=area/2;
	}
	sort(ans,ans+ansc,greater<db>());
	printf("%d %.6f %.6f\n",ansc,ans[0],ans[ansc-1]);
	int q; scanf("%d",&q);
	while (q--){
		int t; scanf("%d",&t);t--;
		if (t>=ansc) puts("Invalid question");
		else printf("%.6f\n",ans[t]);
	}
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 993ms, 内存消耗: 114960K, 提交时间: 2019-07-21 18:00:23

#include <bits/stdc++.h>
#define pb push_back
const double eps=1e-8;
using namespace std;
vector<int>G[1005];
vector<double>S;
vector<int>E[1005*1005];
vector<bool>vis[1005*1005];
int n;
int sgn(double x){
	if(fabs(x)<eps)return 0;
	if(x<0)return -1;
	return 1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	double operator^(const Point& b)const{return x*b.y-y*b.x;}
	Point operator+(const Point& b)const{return Point(x+b.x,y+b.y);}
	Point operator-(const Point& b)const{return Point(x-b.x,y-b.y);}
}a[5205];
vector<Point>P;
bool cmp(int a,int b){
	if(sgn(P[a].x-P[b].x)==0)return P[a].y<P[b].y;
	return P[a].x<P[b].x;
}
Point cross(Point s1,Point e1,Point s2,Point e2){
	Point u=s1-s2,v=e1-s1,w=e2-s2;
	Point p;
	p.x=(w^u)/(v^w)*v.x+s1.x;
	p.y=(w^u)/(v^w)*v.y+s1.y;
	return p;
}
void build(){
	for(int i=0;i<n;i++)for(int j=i+1;j<n;j++){
		if(sgn((a[2*i]-a[2*i+1])^(a[2*j]-a[2*j+1]))==0)continue;
		P.pb(cross(a[2*i],a[2*i+1],a[2*j],a[2*j+1]));
		G[i].pb(P.size()-1);//i这条直线上有P[size()-1]这个点,标号 
		G[j].pb(P.size()-1);
	}
	for(int i=0;i<n;i++){
		sort(G[i].begin(),G[i].end(),cmp);
		for(int j=0;j<G[i].size()-1;j++){
			E[G[i][j]].pb(G[i][j+1]);
			E[G[i][j+1]].pb(G[i][j]);
		}
	}
	for(int i=0;i<P.size();i++)vis[i]=vector<bool>(E[i].size(),0);
}
int st;
vector<Point>tmp;
bool dfs(int u,int fa){
	tmp.pb(P[u]);
	if(u==st){
		double s=0.0;
		for(int i=0;i<tmp.size()-1;i++)s+=(tmp[i]^tmp[i+1]);
		s+=(tmp[tmp.size()-1]^tmp[0]); 
		S.pb(fabs(s)*0.5);
		return 1;
	}
	int Min=-1,num=-1;
	for(int i=0;i<E[u].size();i++){
		int v=E[u][i];
		if(v==fa||vis[u][i])continue;
		if(sgn((P[v]-P[u])^(P[u]-P[fa]))<0 && 
			(Min==-1||sgn((P[v]-P[u])^(P[Min]-P[u]))<0))Min=v,num=i;
	}
	if(Min==-1)return 0;
	if(dfs(Min,u)){
		vis[u][num]=1;
		return 1;
	}
	return 0;
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++)scanf("%lf%lf%lf%lf",&a[2*i].x,&a[2*i].y,&a[2*i+1].x,&a[2*i+1].y);
	
	build();//for(int i=0;i<P.size();i++)cout<<P[i].x<<" "<<P[i].y<<endl;
	for(int i=0;i<P.size();i++){
		st=i;
		for(int j=0;j<E[i].size();j++){
			if(vis[i][j]==0){
				tmp.clear();
				if(dfs(E[i][j],i))vis[i][j]=1;
			}
		}			
	}
	sort(S.begin(),S.end());
	reverse(S.begin(),S.end());
	printf("%d %.5lf %.5lf\n",S.size(),S[0],S[S.size()-1]);
	int x,q;
	scanf("%d",&q);
	while(q--){
		scanf("%d",&x);
		if(x>S.size())printf("Invalid question\n");
		else printf("%.5lf\n",S[x-1]);
	}
	return 0;
} 

上一题