2 1 0 0 1 6 -100 0 90 -50 0 1 -20 0 1 100 0 90 47 0 1 23 0 1
Alice Bob
顯然圓的包括關係可以構成一片森林,而後問題就可以轉化爲:每一步可以刪除森林的一棵樹或者某樹的一棵子樹。不能刪者輸。php
這樣。問題就變成經典的樹上刪邊遊戲了。ios
樹上刪邊遊戲有一個很是重要的結論:葉子節點的SG值爲0,中間節點的SG值爲它的所有子節點的SG值加1後的異或和。(證實詳見賈志豪論文《組合遊戲略述——淺談SG遊戲的若干拓展及變形》)算法
現在。咱們的主要問題就是怎樣把圓的包括關係轉化爲森林。這裏要用到圓的掃描線算法。首先對於每個圓。建立兩個時間點,一個進入一個離開。再對所有時間點從小到大排序。ide
而後逐個處理時間點。用set維護所有圓。每遇到一個進入時間。分狀況討論圓的位置關係。而後把這個圓插入set中。每遇到一個離開時間,從set中刪除這個圓。post
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<set> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 20010 using namespace std; int t,n,cnt,tt,tmp; int head[maxn],fa[maxn]; struct cir{int x,y,r;}a[maxn]; struct edge_type{int next,to;}e[maxn*2]; struct bor { int x,f,id; friend bool operator < (bor a,bor b) { if (a.x==b.x) return a.f<b.f; return a.x<b.x; } }q[maxn*2]; double get_h(int id,int x,int opt) { return a[id].y+opt*sqrt(a[id].r*a[id].r-(a[id].x-x)*(a[id].x-x)); } struct pos { int id,opt; pos(int a=0,int b=0){id=a;opt=b;} friend bool operator < (pos a,pos b) { if (a.id==b.id) return a.opt<b.opt; return get_h(a.id,tmp,a.opt)<get_h(b.id,tmp,b.opt); } }; set<pos> s; set<pos>::iterator it; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y) { e[++cnt]=(edge_type){head[x],y}; head[x]=cnt; fa[y]=x; } inline ll get(int x) { ll ret=0; for(int i=head[x];i;i=e[i].next) ret^=get(e[i].to); return ret+1; } int main() { t=read(); while (t--) { cnt=tt=0; memset(fa,0,sizeof(fa)); memset(head,0,sizeof(head)); n=read(); F(i,1,n) { a[i].x=read();a[i].y=read();a[i].r=read(); q[++tt]=(bor){a[i].x-a[i].r,1,i}; q[++tt]=(bor){a[i].x+a[i].r,-1,i}; } sort(q+1,q+tt+1); F(i,1,tt) { if (q[i].f==1) { tmp=q[i].x; it=s.lower_bound(pos(q[i].id,1)); if (it!=s.end()) { if (it->opt==1) add_edge(it->id,q[i].id); else if (fa[it->id]) add_edge(fa[it->id],q[i].id); } s.insert(pos(q[i].id,1)); s.insert(pos(q[i].id,-1)); } else { s.erase(pos(q[i].id,1)); s.erase(pos(q[i].id,-1)); } } ll sum=0; F(i,1,n) if (!fa[i]) sum=sum^get(i); puts(sum?"Alice":"Bob"); } }