• [CF1019D]Large Triangle


    题面

    http://codeforces.com/contest/1019/problem/D

    题解

    如果我们确定了三角形的底边,就同时确定了顶点到底边的距离。

    我们想要实现的是依次枚举底边时,所有的点都已经按照到此底边的距离(分正负)排好序,这样就可以通过二分查找判答案了。

    考虑对于两个点u,v,底边l,u到l和v到l的距离的大小关系。发现这两者的大小关系当且仅当l与uv连线平行或共线时发生变化。

    因此,算法的流程就出来了:将所有的底边按极角排序。一开始,将所有点按照y坐标排序,并记为序列S。依次枚举排好序后的底边,设这个底边是原图中的点u,v连接而成,那么此时u,v在S中一定相邻。交换它们。依次进行,则S就是我们时刻维护的,将所有点以到当前底边距离为关键字的有序序列,在S中二分查找判答案即可。

    时间复杂度(O(n^2 log n))

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define ld long double
    #define rg register
    #define In inline
    
    const ld eps = 1e-9;
    const int N = 2000;
    
    In int read(){
    	int s = 0,ww = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    	while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    	return s * ww;
    }
    
    In void write(int x){
    	if(x < 0)putchar('-'),x = -x;
    	if(x > 9)write(x / 10);
    	putchar('0' + x % 10);
    }
    
    In int sgn(ld x){return x < -eps ? -1 : x > eps;}
    
    In ld sqr(ld x){return x * x;}
    
    struct vec{
    	ld x,y;
    	vec(){}
    	vec(ld _x,ld _y){x = _x,y = _y;}
    	In friend vec operator + (vec a,vec b){
    		return vec(a.x + b.x,a.y + b.y);
    	}
    	In friend vec operator - (vec a,vec b){
    		return vec(a.x - b.x,a.y - b.y);
    	}
    	In friend vec operator * (vec a,ld k){
    		return vec(a.x * k,a.y * k);
    	}
    	In friend vec operator / (vec a,ld k){
    		return vec(a.x / k,a.y / k);
    	}
    	In friend ld Cross(vec a,vec b){
    		return a.x * b.y - a.y * b.x;
    	}
    	In friend ld Dot(vec a,vec b){
    		return a.x * b.x + a.y * b.y;
    	}
    	In friend bool InUpper(vec a){
    		int k;
    		return ((k=sgn(a.y)) > 0 || (k==0&&sgn(a.x)>0)); 
    	}
    	In friend ld len(vec a){
    		return sqrt(sqr(a.x) + sqr(a.y));
    	}
    	In friend vec Rot90(vec a){
    		return vec(a.y,-a.x);
    	}
    };
    
    struct seg{
    	vec A,B;
    	seg(){}
    	seg(vec _A,vec _B){A = _A,B = _B;}
    	In friend ld len(seg a){
    		return len(a.B - a.A);
    	}
    };
    
    vec Upward(vec p,ld d,vec v){
    	ld Len = len(v);
    	return p + v * d / Len;
    }
    
    In ld dis(vec p,seg a){
    	return Cross(a.B - p,a.A - p) / len(a);
    }
    
    pair<int,int>pr[N*N+5];
    vec p[N+5],s[N+5];
    int rk[N+5];
    ld S;
    int n;
    
    In bool cmp1(pair<int,int>i,pair<int,int>j){
    	seg a = seg(p[i.first],p[i.second]),b = seg(p[j.first],p[j.second]);
    	int k1 = InUpper(a.B-a.A),k2 = InUpper(b.B-b.A);
    	if(k1 != k2)return k1 < k2;
    	return sgn(Cross(a.B-a.A,b.B-b.A)) > 0;
    }
    
    In bool cmp2(vec a,vec b){
    	int k;
    	if((k=sgn(a.y-b.y)) != 0)return k > 0;
    	return sgn(a.x - b.x) > 0;
    }
    
    seg curp;
    
    In bool cmp3(vec a,vec b){
    	return dis(a,curp) > dis(b,curp);
    }
    
    void PrAns(vec a,vec b,vec c){
    	puts("Yes");
    	write((int)round(a.x)),putchar(' '),write((int)round(a.y)),putchar('
    ');
    	write((int)round(b.x)),putchar(' '),write((int)round(b.y)),putchar('
    ');
    	write((int)round(c.x)),putchar(' '),write((int)round(c.y)),putchar('
    ');
    }
    
    int main(){
    	n = read();cin>>S;//scanf("%llf",&S);
    	for(rg int i = 1;i <= n;i++){
    		int x = read(),y = read();
    		p[i] = vec(x,y);
    	}
    	sort(p + 1,p + n + 1,cmp2);
    	for(rg int i = 1;i <= n;i++)rk[i] = i,s[i] = p[i];
    	int cnt = 0;
    	for(rg int i = 1;i <= n;i++)
    		for(rg int j = 1;j <= n;j++){
    			if(i == j || InUpper(p[j]-p[i]))continue;
    			pr[++cnt] = make_pair(i,j);
    		}
    	sort(pr + 1,pr + cnt + 1,cmp1);
    	for(rg int k = 1;k <= cnt;k++){
    		int i = pr[k].first,j = pr[k].second;
    		curp = seg(p[i],p[j]);
    		swap(s[rk[i]],s[rk[j]]);
    		swap(rk[i],rk[j]);
    		ld h = 2 * S / len(curp.B - curp.A);
    		int pos = lower_bound(s + 1,s + n + 1,Upward(curp.A,h,Rot90(curp.B-curp.A)),cmp3) - s;
    		if(sgn(fabs(dis(s[pos],curp))-h) == 0){
    			PrAns(s[pos],p[i],p[j]);
    			return 0;
    		}
    		pos = lower_bound(s + 1,s + n + 1,Upward(curp.A,-h,Rot90(curp.B-curp.A)),cmp3) - s;
    		if(sgn(fabs(dis(s[pos],curp))-h) == 0){
    			PrAns(s[pos],p[i],p[j]);
    			return 0;
    		}
    	}
    	puts("No");
    	return 0;
    }
    
  • 相关阅读:
    团队冲刺第一天
    leetcode整理
    eclipse 中JSP环境搭建
    java期末小结
    桌面宠物online------------------面对对象程序综合设计2020年
    java
    4.3 jmu-Java-03面向对象-06-继承覆盖综合练习-Person、Student、Employee、Company (20分)
    选择
    算法---分支限定0/1背包--蚁群算法
    博客园特效
  • 原文地址:https://www.cnblogs.com/xh092113/p/12364820.html
Copyright © 2020-2023  润新知