题解:P12764 [POI 2018 R3] 两个棋子 Two stones
Solution
和 这道题 几乎一模一样。
问题转化为:给你一组向量
设最终的向量和是
显然不存在和
结论也和那道题一模一样了,极角排序之后跑一个双指针即可。注意特判向量贡献的情况(需要算出是同向还是反向。)
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=200000+10;
int n,x[MAXN],y[MAXN];
int gid(pair<int,int> p) {
if(p.first>0&&p.second>=0) return 1;
if(p.first<=0&&p.second>0) return 2;
if(p.second<=0&&p.first<0) return 3;
return 4;
}
int solve(int sx,int sy,int tx,int ty) {
int px=sx-tx,py=sy-ty;
tx-=px,ty-=py;
return tx*tx+ty*ty;
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
vector<pair<int,int>> vc;
ffor(i,1,n) {
cin>>x[i]>>y[i];
if(x[i]!=0||y[i]!=0) vc.push_back({x[i],y[i]});
}
sort(vc.begin(),vc.end(),[](pair<int,int> A,pair<int,int> B) {
if(gid(A)!=gid(B)) return gid(A)<gid(B);
return A.first*B.second>A.second*B.first;
});
n=vc.size();
ffor(i,1,n) x[i]=vc[i-1].first,y[i]=vc[i-1].second;
int pos=1,sx=0,sy=0,tx=0,ty=0,ans=0;
ffor(i,1,n) sx+=x[i],sy+=y[i];
tx=x[1],ty=y[1];
ans=max(ans,sx*sx+sy*sy);
ffor(i,1,n) {
ans=max(ans,solve(sx,sy,tx,ty));
if(x[i]*y[i%n+1]-y[i]*x[i%n+1]<0||x[i]*y[i%n+1]-y[i]*x[i%n+1]<0&&(x[i]*x[i%n+1]<0||y[i]*y[i%n+1]<0)) {pos=i%n+1,tx=x[pos],ty=y[pos];continue ;}
while(pos%n+1!=i&&(x[i]*y[pos%n+1]-y[i]*x[pos%n+1]>0||x[i]*y[pos%n+1]-y[i]*x[pos%n+1]==0&&x[i]*x[pos%n+1]>=0&&y[i]*y[pos%n+1]>=0)) {
pos=pos%n+1;
tx+=x[pos],ty+=y[pos],ans=max(ans,solve(sx,sy,tx,ty));
}
tx-=x[i],ty-=y[i],ans=max(ans,solve(sx,sy,tx,ty));
}
cout<<ans;
return 0;
}