Description
在无限大的二维平面的原点(0,0)放置着一个棋子。你有n条可用的移动指令,每条指令可以用一个二维整数向量表
示。每条指令最多只能执行一次,但你可以随意更改它们的执行顺序。棋子可以重复经过同一个点,两条指令的方
向向量也可能相同。你的目标是让棋子最终离原点的欧几里得距离最远,请问这个最远距离是多少?
Input
第一行包含一个正整数n(n<=200000),表示指令条数。
接下来n行,每行两个整数x,y(|x|,|y|<=10000),表示你可以从(a,b)移动到(a+x,b+y)。
Output
输出一行一个整数,即最大距离的平方。
最大距离的向量,由所有在这个向量上投影为正的向量相加得到。扫描线扫一圈枚举这个方向,记录答案。
#include<bits/stdc++.h> typedef long long i64; const int N=2e5+7; int _(){int x;scanf("%d",&x);return x;} int n; struct pos{ int x,y; double a; bool operator<(const pos&w)const{return a<w.a;} }ps[N*2]; const double pi=acos(-1); int main(){ n=_(); for(int i=1;i<=n;++i){ ps[i].x=_(); ps[i].y=_(); ps[i].a=atan2(ps[i].y,ps[i].x); if(!ps[i].x&&!ps[i].y)--i,--n; } std::sort(ps+1,ps+n+1); int sx=0,sy=0; i64 ans=0; for(int i=1,j=1;i<=n;++i){ ps[n+i]=(pos){ps[i].x,ps[i].y,ps[i].a+pi*2}; for(;j<n+i&&ps[j].a-ps[i].a<pi+1e-13;++j){ sx+=ps[j].x; sy+=ps[j].y; i64 v=(i64)sx*sx+(i64)sy*sy; if(v>ans)ans=v; } sx-=ps[i].x; sy-=ps[i].y; i64 v=(i64)sx*sx+(i64)sy*sy; if(v>ans)ans=v; } printf("%lld\n",ans); return 0; }