time limit: 40 sec
memory limit: 1024 mb
submit: 116
solved: 52 [
submit][
status][
discuss]
alice和bob在玩遊戲。有n個節點,m條邊(0<=m<=n-1),構成若干棵有根樹,每棵樹的根節點是該連通塊內編號最
小的點。alice和bob輪流操作,每回合選擇乙個沒有被刪除的節點x,將x及其所有祖先全部刪除,不能操作的人輸
。注:樹的形態是在一開始就確定好的,刪除節點不會影響剩餘節點父親和兒子的關係。比如:1-3-2 這樣一條鏈
,1號點是根節點,刪除1號點之後,3號點還是2號點的父節點。問有沒有先手必勝策略。n<=10^5。 4
2 11 2
3 21 2
1 32 0
3 11 2
alice
alice
bobalice [
submit][
status][
discuss]
記sgi為以i為根的子樹的sg值,則當所有連通塊的sg值都統計好時,就可以用sg定理求解了
每個sg值可以通過暴力o(n)列舉轉移統計,但這樣複雜度是o(n^2)的
在dfs過程中遞迴地統計sg值,如果是葉子節點,顯然sg值為1
當需要統計x的sg值的時候,x的所有後代的sg值肯定都已經統計好了
假設其中乙個轉移,是選擇了節點y,那麼要把鏈(x,y)上的點全部刪除
此時剩下的就是這條鏈上每個節點的所有兒子,就是圖中的三角形了
那麼這時候的sg值就是那些三角形的根的sg值的xor和
對於每個點,維護一棵trie,在遞迴結束的時候與其它兒子的trie一起合併
但是在合併前,trie內的值肯定是要改變的,觀察發現,這個改變,就是每個數都xor上乙個數字
也就是說,假設x的乙個兒子z的trie,要把它的資訊給x,
那麼z的trie裡面的所有數字都要xor上x除了z的其它兒子的sg值xor和
就要實現trie裡同時xor上乙個數,打個懶惰標記就解決了
具體的,trie每乙個節點記錄是第幾層,記錄標記,生效的時候對應就是交換兒子
trie合併就像線段樹合併就行了
有了trie,mex操作在trie上二分即可
總複雜度是o(nlog10^9)
#include#includeusing namespace std;
const int maxn = 1e5 + 10;
const int t = 20;
const int n = 15;
int case,n,m,cnt,ans,rt[maxn],ch[maxn*t*n][2],mark[maxn*t*n],l[maxn*t*n],sg[maxn],sum[maxn];
bool all[maxn*t*n],vis[maxn];
vector v[maxn];
void clear()
void pushdown(int o)
int merge(int o1,int o2)
void insert(int o,int k)
int nex = k & (1 << l[o]) ? 1 : 0;
if (!ch[o][nex]) ch[o][nex] = ++cnt,l[cnt] = l[o] - 1;
insert(ch[o][nex],k);
if (all[ch[o][0]] && all[ch[o][1]]) all[o] = 1;}
int query(int o)
return ret;}
void dfs(int x,int from)
for (int i = 0; i < v[x].size(); i++)
insert(rt[x],sum[x]); sg[x] = query(rt[x]);}
int getint()
void solve()
for (int i = 1; i <= n; i++)
if (!vis[i]) vis[i] = 1,dfs(i,0),ans ^= sg[i];
puts(ans ? "alice" : "bob"); clear();}
int main()
BZOJ4730 Alice和Bob又在玩遊戲
傳送門 首先可以看出這是一道博弈論的題,我們考慮對於每一棵樹求出sg。存在這樣兩種情況 1.去掉根,那麼這棵樹的sg是其所有點的sg異或和。2.去掉子樹中的乙個點,那麼這棵樹的sg是其所有點的sg異或和再異或上這個點到根這條路徑上的所有點sg。對於第一種情況很好處理,而第二種情況暴力做法則是列舉每個...
bzoj4730 Alice和Bob又在玩遊戲
題目鏈結 給出乙個森林,兩個人輪流操作,每次把乙個節點以及它的祖先全部抹去,無節點可以抹去是算輸,問是否存在先手必勝策略。trie樹合併,其實就是線段樹合併。bzoj4134的簡單版 二進位制小心寫錯 bzoj4730 include include include include include ...
Alice和Bob賭糖果 概率 經典
alice和bob賭糖果。規則是這樣的 alice從 l,r 中隨機抽乙個數,bob從 l,r 中隨機抽乙個數,誰抽的數大誰就贏,輸的一方給另一方1顆糖 平局不用給糖 他們會一直賭下去直到有一方沒有糖果為止。alice有n顆糖果,bob有m顆糖果,求alice將bob的糖果贏完的概率。第一行3個整數...