0
点赞
收藏
分享

微信扫一扫

BZOJ 5099([POI2018]Pionek-极角排序)

闲云困兽 2022-10-24 阅读 55


题意:有n个向量,每个向量可以选择取或者不取,要求选一些向量,使得它们和最大。
假设最终答案的方向向量已知,显然只要取和它点积为正的向量就行。
维护一条过原点的直线,让它转一周,并维护这条直线上方的向量,将它们全取。

#include<bits/stdc++.h> 
using namespace std;
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma
#define
#define
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define
struct point{
ll fi,se;
double ang;
}p[MAXN];
int cmp(point a,point b) {
return a.ang<b.ang;
}
const double PI=acos(-1);
int main()
{
// freopen("bzoj5099.in","r",stdin);
// freopen(".out","w",stdout);
int n=read(),m=0;
For(i,n){
ll x=read(),y=read();
if (x*x+y*y) p[++m]=point{x,y,atan2(y,x)};
}
n=m;
sort(p+1,p+n+1,cmp);
ll ans=0;
ll sx=0,sy=0;
For(i,n) {
p[n+i]=p[i]; p[n+i].ang+=2*PI;
}
for(int i=1,j=1;i<=n;i++) {
while(j<n+i && p[j].ang-p[i].ang<=PI+1e-13) {
sx+=p[j].fi;
sy+=p[j].se;
gmax(ans, sx*sx+sy*sy);
++j;
}
sx-=p[i].fi; sy-=p[i].se;
gmax(ans, sx*sx+sy*sy);
}
cout<<ans<<endl;
return 0;
}


举报

相关推荐

0 条评论