1. 程式人生 > >Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(樹上Nim)

Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(樹上Nim)

ide vector 等於 如果 ace ble 技術 方式 復雜度

題目鏈接:Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree

題意:

給你一棵樹,每個節點有a[i]個蘋果,有兩個人要在這個樹上玩遊戲。

兩個人輪流操作,誰不能操作誰就輸了。

這個樹有一個特性:葉子到根的距離的奇偶性相同。

每次操作可以選一個節點i,和一個數x,x小於當前節點i的蘋果數。

對於節點i,如果是葉子節點,就將這x個蘋果吃掉。

如果是非葉子節點,就將這x個蘋果移向節點i的任意兒子節點。

現在第二個操作的人要交換兩個節點的蘋果,使其能贏,

問有多少種交換方式,必須交換

題解:

仔細分析一下,可以得到是否能贏只與節點深度的奇偶性與葉子節點相同的節點有關。

我們把這些節點放入一個集合S.

所以先將這些節點進行異或一下,得出一個val。如果val等於0,那麽當前局勢就能贏。

現在來考慮交換節點的蘋果。

顯然我們要將這個val變成0,所以對S中所有的數都進行枚舉一下,然後找不在這個集合中,並且交換後能使val變成0的數。

如果val最開始就為0,那麽還要加上S中可以互相交換的個數。和S外可以互相交換的個數。

復雜度O(n)

技術分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3 using namespace std;
 4 typedef long
long ll; 5 const int N=1e5+7; 6 7 vector<int>g[N]; 8 int cnt[1<<24],cnt2[1<<24],n; 9 int a[N],x,is,val,have[N],ed; 10 11 void dfs(int x=1,int d=0,int fa=0) 12 { 13 if(g[x].size()==0){is=(d&1);} 14 for(auto &it:g[x])if(it!=fa)dfs(it,d+1,x); 15 } 16 17 void dfs2(int
x=1,int d=0,int fa=0) 18 { 19 if((d&1)==is)have[++ed]=a[x]; 20 for(auto &it:g[x])if(it!=fa)dfs2(it,d+1,x); 21 } 22 23 int main() 24 { 25 scanf("%d",&n); 26 F(i,1,n)scanf("%d",a+i),cnt[a[i]]++; 27 F(i,2,n) 28 { 29 scanf("%d",&x); 30 g[x].push_back(i); 31 } 32 dfs(),dfs2(); 33 F(i,1,ed)val^=have[i],cnt2[have[i]]++; 34 ll ans=0; 35 F(i,1,ed) 36 { 37 int tmp=val^have[i]; 38 ans+=cnt[tmp]-cnt2[tmp]; 39 } 40 if(!val) 41 { 42 ans+=1ll*ed*(ed-1)/2; 43 ans+=1ll*(n-ed)*(n-ed-1)/2; 44 } 45 printf("%lld\n",ans); 46 return 0; 47 }
View Code

Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(樹上Nim)