CF995C Leaving the Bar

II.CF995C Leaving the Bar

两个\(10^6\)的向量求和/差,是无法做到结果必在\(10^6\)以内的;但是,如果是三个,就可以做到了。

考虑两个向量。则只有它们的夹角在\([\dfrac{2\pi}{3},\dfrac{4\pi}{3}]\)之间时,可以做到。当有三个向量时,则至少存在一对向量满足上述要求,则可以合并。合并完后问题规模便减少\(1\)。则任意大小的答案,都可以经过合并做到只剩两个\(10^6\)级别的向量;取和/差中模长更小的一个答案,即可做到最终答案在\(1.5\times 10^6\)以内。

可以使用并查集维护向量合并的过程。

代码:

#include<bits/stdc++.h>
using namespace std;
const int LIM1=1000000;
const int LIM2=1500000;
int n,fa[100100],A,B;
bool rev[100100];
struct Vector{
	int x,y;
	Vector(int X=0,int Y=0){x=X,y=Y;}
	friend Vector operator +(const Vector &u,const Vector &v){return Vector(u.x+v.x,u.y+v.y);}
	friend Vector operator -(const Vector &u,const Vector &v){return Vector(u.x-v.x,u.y-v.y);}
	friend bool operator <=(const Vector &u,const int &v){return 1ll*u.x*u.x+1ll*u.y*u.y<=1ll*v*v;}
}v[100100];
int main(){
	scanf("%d",&n);
	if(n<=1){puts("1");return 0;}
	for(int i=1;i<=n;i++)scanf("%d%d",&v[i].x,&v[i].y);
	A=1,B=2;
	for(int i=3;i<=n;i++){
		if(v[i]+v[A]<=LIM1){v[i]=v[i]+v[A],fa[A]=i,A=B,B=i;continue;}
		if(v[i]-v[A]<=LIM1){v[i]=v[i]-v[A],fa[A]=i,rev[A]^=1,A=B,B=i;continue;}
		if(v[i]+v[B]<=LIM1){v[i]=v[i]+v[B],fa[B]=i,B=i;continue;}
		if(v[i]-v[B]<=LIM1){v[i]=v[i]-v[B],fa[B]=i,rev[B]^=1,B=i;continue;}
		if(v[B]+v[A]<=LIM1){v[B]=v[B]+v[A],fa[A]=B,A=B,B=i;continue;}
		if(v[B]-v[A]<=LIM1){v[B]=v[B]-v[A],fa[A]=B,rev[A]^=1,A=B,B=i;continue;}
	}
	if(v[B]+v[A]<=LIM2)v[B]=v[B]+v[A],fa[A]=B;
	else v[B]=v[B]-v[A],fa[A]=B,rev[A]^=1;
	for(int i=n;i;i--)if(fa[i])rev[i]^=rev[fa[i]];
	for(int i=1;i<=n;i++)printf("%d ",rev[i]?-1:1);
	return 0;
}

原文地址:https://www.cnblogs.com/Troverld/p/14613601.html