Description
Input
Output
Sample Input
2 -2
-2 -2
0 2
3 1
-3 1
Sample Output
HINT
题解:假如我们已经确定了最终向量的方向,那么我们就会选择所有在这个方向上投影为正的向量。于是我们将所有向量按极角排序,然后枚举所有方向,用前缀和维护向量的和。可以先将序列倍长,然后用双指针法扫一遍即可。
不过需要注意的是,我们枚举的方向不仅是所有向量的方向,还有所有向量之间间隔的方向,所以我们在每个指针移动的时候都更新一下答案即可。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=200010; int n; ll ans; struct node { int x,y; double a; }p[maxn<<1]; ll sx[maxn<<1],sy[maxn<<1]; bool cmp(const node &a,const node &b) { return a.a<b.a; } inline void check(int l,int r) { if(l<=r) ans=max(ans,(sx[r]-sx[l-1])*(sx[r]-sx[l-1])+(sy[r]-sy[l-1])*(sy[r]-sy[l-1])); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } int main() { n=rd(); int i,j; for(i=1;i<=n;i++) p[i].x=rd(),p[i].y=rd(),p[i].a=atan2(p[i].x,p[i].y),p[i+n]=p[i],p[i+n].a+=2*pi; sort(p+1,p+2*n+1,cmp); for(i=1;i<=2*n;i++) sx[i]=sx[i-1]+p[i].x,sy[i]=sy[i-1]+p[i].y; for(i=j=1;i<=2*n;i++) { for(;j<i&&p[j].a<=p[i].a-pi;j++,check(j,i-1)); check(j,i); } for(;j<=2*n;check(j,2*n),j++); printf("%lld",ans); return 0; }//2 1 10 1 -10
| 欢迎来原网站坐坐! >原文链接<