BZOJ 4520: [Cqoi2016]K遠點對

BZOJ AC 300 紀念!!!

做K次凸包,每次旋轉卡殼找到一對最遠點,刪掉他們並把他們構成的點對加入候選集合

於是候選集合的大小爲O(nk)的

總複雜度O(nklogn)

(好像會T)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
const int inf=2*(1e9);
const int N=100000+5;
vector<ll>d[205];
struct point{
	ll x,y;
	int id;
	bool operator < (const point &p)const{
		return x==p.x?y<p.y:x<p.x;
	}
}p[N],ch[N];
bool del[N];
point operator - (point a,point b){
	return (point){a.x-b.x,a.y-b.y};
}
ll cross(point a,point b){
	return a.x*b.y-a.y*b.x;
}
ll cross(point a,point b,point c){
	return cross(b-a,c-a);
}
ll sqr(ll x){return x*x;}
ll dist(point a,point b){
	return sqr(a.x-b.x)+sqr(a.y-b.y);
}
int n,m,tot;
void andrew(){
	m=0;  
    rep(i,1,n){
    	if(del[p[i].id])continue;
    	while(m>1&&cross(ch[m-2],ch[m-1],p[i])<=0)m--;  
       	ch[m++]=p[i];  
    }  
   	int k=m;  
    per(i,n-1,1){
    	if(del[p[i].id])continue;
    	while(m>k&&cross(ch[m-2],ch[m-1],p[i])<=0)m--;  
        ch[m++]=p[i];  
    }  
    if(n)m--;  
}
void insert(point t){
	tot++;
	del[t.id]=true;
	rep(k,1,n)
	if(!del[p[k].id])
	d[tot].push_back(dist(t,p[k]));
	sort(d[tot].begin(),d[tot].end());
}
bool in(int id){
	rep(i,0,m)if(ch[i].id==id)return true;
	return false;
}
int find(int x){
	rep(i,0,m)if(ch[i].id==x)return i;
	return -1;
}
ll iabs(ll x){return x<0?-x:x;}
ll area(point a,point b,point c){
	return iabs(cross(a,b,c));
}
void rotating(){
	if(m==2){
		insert(ch[0]);insert(ch[1]);
		return ;
	}
	point p1,p2;
	ll mx=-1;
	int j=1;
	rep(i,0,m-1){
		while(area(ch[i],ch[i+1],ch[j])<area(ch[i],ch[i+1],ch[j+1]))j=(j+1)%m;
		if(dist(ch[i],ch[j])>mx)
		mx=dist(ch[i],ch[j]),
		p1=ch[i],p2=ch[j];
	}
	insert(p1);insert(p2);
}
struct Node{
	ll d;
	int i,j;
	bool operator < (const Node &x)const{
		return d<x.d;
	}
};
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int t,k;scanf("%d%d",&n,&k);t=n;
	rep(i,1,n)scanf("%lld%lld",&p[i].x,&p[i].y),p[i].id=i;
	sort(p+1,p+1+n);
	rep(i,1,k){
		if(t==1)break;
		andrew();
		rotating();
		t-=2;
	}
	priority_queue<Node>q;
	rep(i,1,tot)
	if((int)d[i].size())
	q.push((Node){d[i][(int)d[i].size()-1],i,(int)d[i].size()-1});
	k--;
	while(k--){
		Node tmp=q.top();q.pop();
		if(!tmp.j)continue;
		q.push((Node){d[tmp.i][tmp.j-1],tmp.i,tmp.j-1});
	}
	printf("%lld\n",q.top().d);
	return 0;
}


發佈了293 篇原創文章 · 獲贊 3 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章