题解:P5955 [POI2018] Pionek
ZhongYuLin · · 题解
显然只有处于一个半平面内的向量集合才有可能成为答案。去考虑枚举半平面。考虑用一个与分割线正交的方向向量来刻画这个半平面
我们将所有的向量按辐角主值排序。设答案向量为
对于区间右端点,如果当前向量与
对于区间左端点,如果当前向量与
然而,我们不必构造
注意一下
复杂度
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=4e5+3;
const double PI=acos(-1),eps=1e-6;
struct Vec{
int x,y;
double tan;
}v[N];
int n;
double calc(double t1,double t2){return min(abs(t1-t2),2*PI-abs(t1-t2));}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i){
cin>>v[i].x>>v[i].y;
if(!v[i].x&&!v[i].y){--i,--n;continue;}
v[i].tan=atan2(v[i].y,v[i].x);
if(v[i].tan<0)v[i].tan+=2*PI;
}
sort(v+1,v+1+n,[&](Vec x,Vec y){return x.tan<y.tan;});
for(int i=1;i<=n;++i)v[i+n]=v[i];
int l=1,r=1;double it=PI/2;ll x=0,y=0,ans=0;
for(;it<=PI*5/2;it+=eps){
double at=it;
if(at>2*PI)at-=2*PI;
while(r<=l+n-1&&calc(v[r].tan,at)*2<=PI)
x+=v[r].x,y+=v[r].y,ans=max(ans,x*x+y*y),++r;
while(l<r&&calc(v[l].tan,at)*2>PI)
x-=v[l].x,y-=v[l].y,ans=max(ans,x*x+y*y),++l;
}printf("%lld\n",ans);
return 0;
}