CQOI2016 K远点对 计算几何

辣鸡计算几何,写的我意识模糊

我们知道每次的最远点一定在凸包上面

于是我们就可以每次搞出来凸包,然后卡壳最远点,保存一些点乱搞一发就可以了

最开始想用堆维护结果委的不行

/* ***********************************************
Author        :BPM136
Created Time  :2016/4/19 19:07:13
File Name     :B.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<utility>
#include<vector>
#include<functional>
#include<numeric>
#include<memory>
#include<iterator>
#define LL long long
#define DB double
#define LB long double
#define UL unsigned long
#define ULL unsigned long long
#define get(a,i) a&(1<<(i-1))
#define PAU putchar(32)
#define ENT putchar(10)
#define clr(a,b) memset(a,b,sizeof(a))
#define fo(_i,_a,_b) for(int _i=_a;_i<=_b;_i++)
#define fd(_i,_a,_b) for(int _i=_a;_i>=_b;_i--)
#define efo(_i,_a) for(int _i=last[_a];_i!=0;_i=e[_i].next)
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#define mkd(x) freopen(#x".in","w",stdout);
#define setlargestack(x) int size=x<<20;char *p=(char*)malloc(size)+size;__asm__("movl %0, %%esp\n" :: "r"(p));
#define end system("pause")
using namespace std;
LL read()
{
         LL f=1,d=0;char s=getchar();
         while (s<48||s>57){if (s==45) f=-1;s=getchar();}
         while (s>=48&&s<=57){d=d*10+s-48;s=getchar();}
         return f*d;
}
LL readln()
{
       LL f=1,d=0;char s=getchar();
       while (s<48||s>57){if (s==45) f=-1;s=getchar();}
       while (s>=48&&s<=57){d=d*10+s-48;s=getchar();}
       while (s!=10) s=getchar();
       return f*d;
}
inline void write(LL x)
{
    if(x==0){putchar(48);return;}if(x<0)putchar(45),x=-x;
    int len=0,buf[20];while(x)buf[len++]=x%10,x/=10;
    for(int i=len-1;i>=0;i--)putchar(buf[i]+48);return;
}
inline void writeln(LL x){write(x);ENT;}
#define N 100005
#define K 105
struct point
{
	LL x,y;
	DB ag;
	void OUT()
	{
		write(x);PAU;write(y);
	}
}po[N];
struct node
{
	LL len;
	int id,id2;
	bool operator<(const node &a)const
	{
		return (LL)len<a.len;
	}
	void OUT()
	{
		cout<<len<<endl;
		cout<<po[id].x<<' '<<po[id].y<<endl;
		cout<<po[id2].x<<' '<<po[id2].y<<endl;
		cout<<endl;
	}
};
int n,m;

LL cross(int p,int a,int b){
	LL x1=po[a].x-po[b].x;
	LL y1=po[a].y-po[b].y;
	LL x2=po[p].x-po[a].x;
	LL y2=po[p].y-po[a].y;
	return x1*y2-x2*y1;
}

LL cross(point p,point a,point b){
	LL x1=a.x-b.x;
	LL y1=a.y-b.y;
	LL x2=p.x-a.x;
	LL y2=p.y-a.y;
	return x1*y2-x2*y1;
}

bool cmppoint(point a,point b){
	LL cj=cross(a,b,po[1]);
	return cj<0;
}

int tb[N],nm=0;
void Graham(){
	int k=1;
	fo(i,2,n){
		if(po[k].y>po[i].y||(po[k].y==po[i].y&&po[k].x>po[i].x))k=i;
	}
	swap(po[k],po[1]);tb[++nm]=1;
	sort(po+2,po+n+1,cmppoint);
//	fo(i,1,n)cout<<po[i].x<<' '<<po[i].y<<endl;cout<<endl;
	fo(i,2,n){
		while(nm>1&&cross(i,tb[nm],tb[nm-1])<0)nm--;
		tb[++nm]=i;
	}
//	fo(i,1,nm)cout<<tb[i]<<' ';cout<<endl;
//	fo(i,1,nm)cout<<po[tb[i]].x<<' '<<po[tb[i]].y<<endl;cout<<endl;
}

priority_queue<node>q;
LL calc(int a,int b){
	return (LL)(po[a].x-po[b].x)*(po[a].x-po[b].x)+(po[a].y-po[b].y)*(po[a].y-po[b].y);
}

int lft[N];
void RCA(){
	int k=1;
	memset(lft,0,sizeof(lft));
	fo(i,1,nm){
		while(calc(tb[i],tb[k])<calc(tb[i],tb[k%nm+1]))k=k%nm+1;
		node t;t.len=calc(tb[i],tb[k]), t.id=tb[i], t.id2=tb[k];
		if(lft[tb[k]]!=tb[i]){
			q.push(t);
		}
		lft[tb[i]]=tb[k];
		if(lft[tb[k]]==0||t.len>calc(lft[tb[k]],tb[k]))lft[tb[k]]=tb[i];
	}
}

LL Ans[N+K];
bitset<N>v;
/*
void work(){
	int Times=0;
	while(Times<m)
	{
		node t=q.top();q.pop();int mxlen=0;int mxid=-1,now=t.id;
		t.OUT();
		fo(j,1,n){
			if(j==t.id2||j==t.id)continue;
			if(mxid==-1&&calc(now,j)<t.len)mxid=j;
			else {
				int tmplen=calc(now,j);
				if(tmplen>t.len)continue;
				if(tmplen>mxlen){
					mxlen=tmplen;
					mxid=j;
				}
			}
		}
		if(mxid!=-1){
			t.len=mxlen;
			t.id2=mxid;
			q.push(t);
			Times++;
		}
	}
	cout<<"Ans::"<<' '<<q.top().len<<endl;
	node tt=q.top();tt.OUT();
	fo(i,1,n)po[i].OUT();
}
*/

bool cmpAns(LL a,LL b){
	return a>b;
}
/*
int tmp[K],nk=0;
void work()
{
	v.reset();int tt=0;
	while(1){
		node t=q.top();q.pop();
		int x=t.id,y=t.id2;
		if(x>y)swap(x,y);
		if(v[y]==1)continue;
		if(v[x]==1)continue;
		fo(i,1,n){
			if(v[i])continue;
			if(i==y)continue;
			int tmplen=calc(i,y);
			if(nk==0||tmplen>tmp[m])Ans[++tt]=tmplen;
			po[i].OUT();PAU;po[y].OUT();ENT;writeln(tmplen);
		}
		if(tt<m)continue;
		sort(Ans+1,Ans+tt+1,cmpAns);
		if(nk==0){
			fo(i,1,m)tmp[++nk]=i;
			tt=m;
		}else{
			int flag=1;
			fo(i,1,m){
				if(tmp[i]!=Ans[i])flag=0;
				tmp[i]=Ans[i];
			}
			tt=m;
			if(flag)return;
		}
		v[y]=1;
		fo(i,1,m)cout<<Ans[i]<<' ';cout<<endl;
	}
}
*/

LL calc(point a,point b){
	LL x=a.x-b.x;
	LL y=a.y-b.y;
	return x*x+y*y;
}

const DB eps=1e-10;
bool cmppo(point a,point b){
	if(fabs(a.ag-b.ag)<eps)return calc(po[1],a)<calc(po[1],b);
	return a.ag<b.ag;
}

void work(){
	Ans[0]=-1;int kt=1;v.reset();
	fo(i,2,n){
		if(po[kt].y>po[i].y||(po[kt].y==po[i].y&&po[kt].x>po[i].x))kt=i;
	}
	swap(po[kt],po[1]);
	fo(i,2,n){
		po[i].ag=atan2(po[i].y-po[1].y,po[i].x-po[1].x);
	}
	sort(po+2,po+n+1,cmppo);
	int Ansnum=0;
//	fo(i,1,n)cout<<po[i].x<<' '<<po[i].y<<endl;cout<<endl;
	fo(Times,1,m){
		nm=0;
		fo(i,1,n){
			if(v[i])continue;
			while(nm>1&&cross(i,tb[nm],tb[nm-1])<0)nm--;
			tb[++nm]=i;
		}
		tb[0]=tb[nm];tb[nm+1]=tb[1];
		int k=1;LL tmpAns=-1;int Ansi,Ansj;
		fo(i,1,nm){
			while((LL)calc(tb[i],tb[k])<=calc(tb[i],tb[k%nm+1]))k=k%nm+1;
			if(calc(tb[i],tb[k])>tmpAns){
				tmpAns=calc(tb[i],tb[k]);
				Ansi=tb[i], Ansj=tb[k];
			}
		}
		if(Ansi>Ansj)swap(Ansi,Ansj);
		v[Ansj]=1;int kn=0;
		fo(i,1,n){
			if(v[i])continue;
			if(calc(i,Ansj)>Ans[Ansnum]){
				Ans[Ansnum+(++kn)]=calc(i,Ansj);
			}
		}
		if(kn==0)break;
		sort(Ans+1,Ans+Ansnum+kn+1,cmpAns);
		Ansnum=min(m,Ansnum+kn);
	}
}



int main()
{
	file(B);
	n=read(),m=read();
	fo(i,1,n){
		po[i].x=read();
		po[i].y=read();
	}
//	Graham();
//	RCA();
	work();
	writeln(Ans[m]);
	return 0;
}


你可能感兴趣的:(计算几何)