题目
n<=1e5
思路
60% 由于图上只有两种颜色,分别求出凸包然后明科夫斯基差后求出最远点
即可
100% 现在有多种颜色,就比较难办了,不过我们可以对于颜色进行分治,
假设现在的序列为 ,现在先求 unique ,
则给这些颜色随便编号 ,将这n个点分成两个集合 和 :颜色
为 的放在集合 里,其他放在 里,这样, 和 中分别选
出一个点来,他们的颜色都是不同的,因此就可以像60%那样当做两种颜色
的情况来做。之后再递归处理 , 即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> node_data;
typedef vector<node_data> hull_data;
const ll MAX=1ll<<40;
const double phi=acos(-1);
template <typename Type> void read_int (Type &a) {
char c=getchar(); bool f=false; a=0;
while ((c<'0'||c>'9')&&c!='-') c=getchar();
if (c=='-') f=true,c=getchar();
while (c>='0'&&c<='9') a=(a<<1)+(a<<3)-48+c,c=getchar();
if (f) a=-a; return;
}
int n,left[250003],right[250003],num; ll ans;
struct node {
ll x,y,col;
double radian;
} d[250003];
bool cmp1 (const node &a,const node &b)
{ return a.col<b.col; }
bool cmp2 (const node &a,const node &b)
{ return a.radian<b.radian; }
hull_data hull[1000003];
bool better (node_data a,node_data b,node_data c) {
if ((b.first-a.first)*(c.second-b.second)-(c.first-b.first)*(b.second-a.second)<=0)
return true;
return false;
}
void solve (int num1,int num2,hull_data&ans) {
ans.clear();
ll x=MAX,y=MAX,o;
for (int i=left[num1];i<=right[num2];i++)
if (d[i].y<y||d[i].y==y&&d[i].x<x)
x=d[i].x,y=d[i].y,o=i;
std::swap(d[left[num1]],d[o]);
for (int i=left[num1]+1;i<=right[num2];i++)
d[i].radian=atan2(d[i].y-d[left[num1]].y,d[i].x-d[left[num1]].x);
std::sort(d+left[num1],d+right[num2]+1,cmp2);
for (int i=left[num1];i<=right[num2];i++) {
if (ans.size()<2) { ans.push_back(node_data(d[i].x,d[i].y)); continue; }
while (ans.size()>=2) {
node_data last1=ans[ans.size()-1],last2=ans[ans.size()-2];
if (!better(last2,last1,node_data(d[i].x,d[i].y))) break;
ans.pop_back();
} ans.push_back(node_data(d[i].x,d[i].y));
}
if (ans.size()>2&&better(ans[ans.size()-2],ans[ans.size()-1],ans[0]))
ans.erase(--(--ans.end()));
return;
}
void print (hull_data&value) {
for (auto iter=value.begin();iter!=value.end();iter++)
printf("%d %d\n",iter->first,iter->second);
puts("~");
return;
}
ll calc_dis (node_data value)
{ return value.first*value.first+value.second*value.second; }
hull_data operator - (const hull_data &val) {
static hull_data ans;
ans=val;
for (auto iter=ans.begin();iter!=ans.end();iter++)
iter->first=-iter->first,
iter->second=-iter->second;
return ans;
}
hull_data::iterator operator + (hull_data::iterator iter,int size)
{ auto ans=iter; while (size--) ++ans; return ans; }
hull_data calc (hull_data a,hull_data b) {
static hull_data ans; ans.clear();
ll x=MAX,y=MAX; hull_data::iterator o1,o2;
for (auto iter=a.begin();iter!=a.end();iter++)
if (iter->second<y||iter->second==y&&iter->first<x)
x=iter->first,y=iter->second,o1=iter;
x=MAX; y=MAX;
for (auto iter=b.begin();iter!=b.end();iter++)
if (iter->second<y||iter->second==y&&iter->first<x)
x=iter->first,y=iter->second,o2=iter;
// print(a); print(b);
ans.push_back(node_data(o2->first+o1->first,o2->second+o1->second));
auto p1=o1,p2=o2,n1=o1+1,n2=o2+1;
int len1=a.size(),len2=b.size();
if (n1==a.end()) n1=a.begin();
if (n2==b.end()) n2=b.begin();
double r1=atan2(n1->second-p1->second,n1->first-p1->first);
if (r1<0) r1+=2*phi;
double r2=atan2(n2->second-p2->second,n2->first-p2->first);
if (r2<0) r2+=2*phi;
while (len1+len2>1) {
if (len1&&(!len2||r1<r2)) {
--len1; node_data next(ans[ans.size()-1].first+n1->first-p1->first,ans[ans.size()-1].second+n1->second-p1->second);
while (ans.size()>=2) {
node_data last1=ans[ans.size()-1],last2=ans[ans.size()-2];
if (!better(last2,last1,next)) break;
ans.pop_back();
} ans.push_back(next);
p1=n1; ++n1;
if (n1==a.end()) n1=a.begin();
r1=atan2(n1->second-p1->second,n1->first-p1->first);
if (r1<0) r1+=2*phi;
} else {
--len2; node_data next(ans[ans.size()-1].first+n2->first-p2->first,ans[ans.size()-1].second+n2->second-p2->second);
while (ans.size()>=2) {
node_data last1=ans[ans.size()-1],last2=ans[ans.size()-2];
if (!better(last2,last1,next)) break;
ans.pop_back();
} ans.push_back(next);
p2=n2; ++n2;
if (n2==b.end()) n2=b.begin();
r2=atan2(n2->second-p2->second,n2->first-p2->first);
if (r2<0) r2+=2*phi;
}
}
if (ans.size()>2&&better(ans[ans.size()-2],ans[ans.size()-1],ans[0]))
ans.erase(--(--ans.end()));
return ans;
}
void divide (int now,int left,int right) {
if (left==right) { solve(left,right,hull[now]); return; }
int mid=left+right>>1;
divide(now<<1,left,mid); divide(now<<1|1,mid+1,right);
if (hull[now<<1].size()>=3&&hull[now<<1|1].size()>=3) {
hull[now]=calc(hull[now<<1],-hull[now<<1|1]);
for (auto iter=hull[now].begin();iter!=hull[now].end();iter++)
ans=std::max(ans,calc_dis(*iter));
// print(hull[now]);
} else {
for (auto iter1=hull[now<<1].begin();iter1!=hull[now<<1].end();iter1++)
for (auto iter2=hull[now<<1|1].begin();iter2!=hull[now<<1|1].end();iter2++)
ans=std::max(ans,calc_dis(node_data(iter1->first-iter2->first,iter1->second-iter2->second)));
}
solve(left,right,hull[now]);
return;
}
int main () {
read_int(n);
for (int i=1;i<=n;i++)
read_int(d[i].x),read_int(d[i].y),
read_int(d[i].col);
std::sort(d+1,d+n+1,cmp1);
int point=1,tail;
while (point<=n) {
tail=point;
while (tail<n&&d[tail+1].col==d[point].col)
++tail;
++num; left[num]=point; right[num]=tail;
for (int i=point;i<=tail;i++)
d[i].col=num;
point=tail+1;
}
divide(1,1,num);
printf("%lld",ans);
return 0;
}