spj
查看原帖
spj
731662
_154楼主2022/7/4 15:24
#include <map>
#include "testlib.h"
#define MAXN 200005

struct Point
{
	int x, y;
	Point(){}
	Point(int _x, int _y) : x(_x), y(_y) {}
	bool operator < (const Point &a) const {
		return x == a.x ? y < a.y : x < a.x;
	}
	Point operator + (const Point &a) const {
		return Point(x + a.x, y + a.y);
	}
	Point operator - (const Point &a) const {
		return Point(x - a.x, y - a.y);
	}
	long long operator * (const Point &a) const {
		return 1LL * x * a.y - 1LL * y * a.x;
	}
	long long operator ^ (const Point &a) const {
		return 1LL * x * a.x + 1LL* y * a.y;
	}
};

Point p[MAXN], q[MAXN];
int n, m, f[MAXN], l[MAXN], r[MAXN];
std::map <Point, int> mp;
std::vector <std::pair<int, int> > ev;

int X;

struct SegCmp
{
	bool operator() (const int i, const int j) const {
		Point &A = q[l[i]], &B = q[r[i]];
		Point &C = q[l[j]], &D = q[r[j]];
		__int128 s = (long long)(B.y - A.y) * (X - A.x) + (long long)A.y * (B.x - A.x);
		__int128 t = (long long)(D.y - C.y) * (X - C.x) + (long long)C.y * (D.x - C.x);
		__int128 CD = D.x - C.x;
		__int128 BA = B.x - A.x;
		return s * CD < t * BA;
	}
};

std::multiset <int, SegCmp> S;

inline int sgn(long long x) { return x < 0 ? -1 : (x > 0); }

inline bool intersect(const Point &A, const Point &B, const Point &C, const Point &D)
{
	int d1 = sgn((B - A) * (C - A)) * sgn((B - A) * (D - A));
	int d2 = sgn((D - C) * (A - C)) * sgn((D - C) * (B - C));
	return d1 < 0 && d2 < 0;
}

inline bool intersect(int i, int j)
{
	//printf("%d %d\n",i,j);
	if (i == -1 || j == -1 || i == j) return false;
	//printf("%d %d\n",i,j);
	//printf("(%d, %d)-(%d, %d)\n",q[l[i]].x,q[l[i]].y,q[r[i]].x,q[r[i]].y);
	//printf("(%d, %d)-(%d, %d)\n",q[l[j]].x,q[l[j]].y,q[r[j]].x,q[r[j]].y);
	
	if (!sgn((q[l[i]] - q[r[i]]) * (q[l[j]] - q[r[j]])))
	{
		if (q[l[i]].x == q[r[i]].x)
		{
			if (q[l[i]].x != q[l[j]].x) return false;
			int iymn = std::min(q[l[i]].y, q[r[i]].y);
			int iymx = std::max(q[l[i]].y, q[r[i]].y);
			int jymn = std::min(q[l[j]].y, q[r[j]].y);
			int jymx = std::max(q[l[j]].y, q[r[j]].y);
			if (iymn < jymn)
			{
				if (iymx <= jymn) return false;
				return true;
			}
			else if (iymn == jymn) return true;
			else
			{
				if (jymn <= iymn) return false;
				return true;
			}
		}
		else if (q[l[i]].y == q[r[i]].y)
		{
			if (q[l[i]].y != q[l[j]].y) return false;
			int ixmn = std::min(q[l[i]].x, q[r[i]].x);
			int ixmx = std::max(q[l[i]].x, q[r[i]].x);
			int jxmn = std::min(q[l[j]].x, q[r[j]].x);
			int jxmx = std::max(q[l[j]].x, q[r[j]].x);
			if (ixmn < jxmn)
			{
				if (ixmx <= jxmn) return false;
				return true;
			}
			else if (ixmn == jxmn) return true;
			else
			{
				if (jxmn <= ixmn) return false;
				return true;
			}
		}
	}
	return intersect(q[l[i]], q[r[i]], q[l[j]], q[r[j]]);
}

int getf(int x){ return x == f[x] ? x : f[x] = getf(f[x]); }

inline void Union(int x, int y)
{
	x = getf(x); y = getf(y);
	if (x != y) f[y] = x;
	return ;
}

bool judge()
{
	sort(ev.begin(), ev.end(), [&](const std::pair<int, int> &x, const std::pair<int, int> &y){ return q[x.first] < q[y.first]; });
	for (auto P : ev)
	{
		int x = P.first, t = P.second;
		X = q[x].x;
		if (t > 0)
		{
			auto up = S.insert(t), dn = up;
			int a = -1, b = -1;
			if (up != S.end()) a = *(++up);
			if (dn != S.begin()) b = *(--dn);
			if (intersect(a, t))
			{
				//puts("Yes");
				return false;
			}
			if (intersect(b, t))
			{
				return false;
			}
		}
		else
		{
			auto up = S.find(-t), dn = up;
			int a = -1, b = -1;
			if (up != S.end()) a = *(++up);
			if (dn != S.begin()) b = *(--dn);
			if (intersect(a, b))
			{
				return false;
			}
			S.erase(-t);
		}
	}
	return true;
}

bool judgeNoX()
{
	ev.clear(); S.clear();
	for (int i = 1; i <= m; i++)
		q[i] = p[i];
	for (int i = 1; i <= n; i++)
	{
		if (q[r[i]] < q[l[i]]) std::swap(l[i], r[i]);
		if (q[l[i]].x != q[r[i]].x)
		{
			ev.push_back({l[i],  i});
			ev.push_back({r[i], -i});
		}
	}
	return judge();
}

bool judgeNoY()
{
	ev.clear(); S.clear();
	for (int i = 1; i <= m; i++)
		q[i] = Point(-p[i].y, p[i].x);
	for (int i = 1; i <= n; i++)
	{
		if (q[r[i]] < q[l[i]]) std::swap(l[i], r[i]);
		if (q[l[i]].x != q[r[i]].x)
		{
			ev.push_back({l[i],  i});
			ev.push_back({r[i], -i});
		}
	}
	return judge();
}

bool judgeXY()
{
	ev.clear(); S.clear();
	for (int i = 1; i <= m; i++)
		q[i] = Point(p[i].x - p[i].y, p[i].x + p[i].y);
	for (int i = 1; i <= n; i++)
	{
		if (q[r[i]] < q[l[i]]) std::swap(l[i], r[i]);
		if (q[l[i]].x != q[r[i]].x)
		{
			ev.push_back({l[i],  i});
			ev.push_back({r[i], -i});
		}
	}
	return judge();
}

int main(int argc, char *argv[])
{
	registerTestlibCmd(argc, argv);
	n = inf.readInt();
	for (int i = 1, p = n << 1; i <= p; i++) f[i] = i;
	for (int i = 1; i <= n; i++)
	{
		int ax = inf.readInt(), ay = inf.readInt();
		int bx = inf.readInt(), by = inf.readInt();
		Point a(ax, ay), b(bx, by);
		mp.insert({a, ++m}); p[m] = a; l[i] = m;
		mp.insert({b, ++m}); p[m] = b; r[i] = m;
		Union(m - 1, m);
	}
	for (int i = 1; i < n; i++)
	{
		int ax = ouf.readInt(), ay = ouf.readInt();
		int bx = ouf.readInt(), by = ouf.readInt();
		Point a(ax, ay), b(bx, by);
		auto A = mp.find(a);
		if (A == mp.end())
			quitf(_wa, "(%d, %d) is not a city", ax, ay);
		auto B = mp.find(b);
		if (B == mp.end())
			quitf(_wa, "(%d, %d) is not a city", bx, by);
		Union(A -> second, B -> second);
		l[i + n] = A -> second; r[i + n] = B -> second;
	}
	n <<= 1; --n;
	for (int i = 2, fa = getf(1); i <= n; i++)
		if (getf(i) != fa)
			quitf(_wa, "City (%d, %d) is not connected.", p[i].x, p[i].y);
	if (!judgeNoX())
	{
		quitf(_wa, "intersection which isn't an endpoint exists.");
	}
	if (!judgeNoY())
	{
		quitf(_wa, "intersection which isn't an endpoint exists.");
	}
	if (!judgeXY())
	{
		quitf(_wa, "intersection which isn't an endpoint exists.");
	}
	quitf(_ok, "OK");
	return 0;
}

话说 LOJ 不是有吗

2022/7/4 15:24
加载中...