HDU 5299 圆扫描线 + 树上删边

几何+博弈的简单组合技

给出n个圆,有包含关系,以这个关系做游戏,每次操作可以选择把一个圆及它内部的圆全部删除,不能操作者输。

圆的包含关系显然可以看做是树型结构,所以也就是树上删边的游戏。

而找圆的包含关系,这题数据不大可用n^2复杂度找。也可以用扫描线,实时记录其节点父亲的情况。3种情况分类讨论一下就可以了。

 

 

/** @Date    : 2017-10-18 20:21:54
  * @FileName: HDU 5299 圆扫描线+树上删边.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoungEarlf@gmail.com)
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 2e4+20;
const double eps = 1e-8;


struct yuu
{
	double x, y, r;
	yuu(){}
	yuu(double _x, double _y, double _r):x(_x), y(_y), r(_r){}
};

yuu pt[N];
double scanx;
struct Node{
	int id, flag;
	Node(){}
	Node(int i, int f):id(i),flag(f){}
	bool operator <(const Node &b) const {
		double dis1 = sqrt(pt[id].r*pt[id].r - (scanx - pt[id].x) * (scanx - pt[id].x));
		double dis2 = sqrt(pt[b.id].r*pt[b.id].r - (scanx - pt[b.id].x) * (scanx - pt[b.id].x));
		double y1 = pt[id].y + flag * dis1;
		double y2 = pt[b.id].y + b.flag * dis2;
		return y1 < y2 || (fabs(y1 - y2) < eps && flag < b.flag);
	}
};

pair<double, int>evt[2*N];
vector<int>edg[N];
set<Node>st;
int cnt[N];
int fa[N];

void init(int n)
{
	for(int i = 0; i <= n; i++)
	{
		fa[i] = 0;
		edg[i].clear();
	}
	st.clear();
}
int get_sg(int x, int pre)
{
	int res = 0;
	for(auto i : edg[x])
	{
		if(i == pre)
			continue;
		res ^= 1 + get_sg(i, x);
	}
	return res;
}

int main()
{
	int T;
	cin >> T;
	while(T--)
	{
		int n;
		scanf("%d", &n);
		init(n);
		for(int i = 1; i <= n; i++)
		{
			double x, y, r;
			scanf("%lf%lf%lf", &x, &y, &r);
			pt[i] = yuu(x, y, r);
			evt[(i-1)*2] = MP(x - r, i);
			evt[(i-1)*2 + 1] = MP(x + r, i + n);
		}
		sort(evt, evt + 2 * n);

		for(int i = 0; i < n * 2; i++)
		{
			scanx = evt[i].fi;
			int t = evt[i].se;
			if(t <= n)
			{
				int up = -1;
				int dw = -1;
				st.insert(Node(evt[i].se, -1));
				auto pos = st.lower_bound(Node(evt[i].se,-1));
				if((++pos) != st.end())
					up = pos->id;
				if((--pos) != st.begin())
					dw = (--pos)->id;
				if(up == dw && ~up)
				{
					fa[evt[i].se] = up;
					edg[up].PB(evt[i].se);
				}
				else if(~dw && ~up)
				{
					if(fa[up] == fa[dw])
					{
						fa[evt[i].se] = fa[up];
						edg[fa[up]].PB(evt[i].se);
					}
					else if(fa[up] == dw)
					{
						fa[evt[i].se] = dw;
						edg[dw].PB(evt[i].se);
					}
					else if(fa[dw] == up)
					{
						fa[evt[i].se] = up;
						edg[up].PB(evt[i].se);
					}
				}
				else edg[0].PB(evt[i].se);
				st.insert(Node(evt[i].se, 1));
			}
			else 
			{
				st.erase(Node(evt[i].se-n, 1));
				st.erase(Node(evt[i].se-n,-1));
			}
		}
		/*for(int i = 0; i <= n; i++,cout<<endl)
		{
			cout<<i<<":";
			for(auto j:edg[i])
				printf("%d ", j);
		}*/
		int sg = get_sg(0, -1);
		printf("%s\n", sg?"Alice":"Bob");
	}
    return 0;
}
posted @ 2017-10-18 21:38  Lweleth  阅读(326)  评论(0编辑  收藏  举报