1. 程式人生 > >20170908 校內模擬賽 遊戲

20170908 校內模擬賽 遊戲

for ret struct 其中 pan std game sca ()

T1.遊戲(game)
小 z 和小 Z 最近迷上了玩 Nim 遊戲,這個遊戲的規則是這樣的:有 n 堆石
子,第 i 堆有 ai 個石子。兩個人輪流操作,每次可以任意取一堆的任意多個石
子,可以取完或者不取完,誰先取不了誰輸。
每次創造一個初始局面過於麻煩, 他們決定把石子聚成很多堆, 又把這些堆
擺成一棵樹,每次選擇一條鏈上的所有石子堆作為初始局面玩遊戲。當然,他們
還經常修改石子堆裏的石子數量。
小 Z 明白這個遊戲是有必勝策略的,所以他總是按照策略行動,並且經常
獲勝。小 z 並不知道獲勝策略,所以他去請教了機智的小 d。在明白了獲勝策略
之後他恍然大悟, 這時他回想起了和小 Z 玩的好多場遊戲, 他想知道其中有哪些
遊戲他一定會失敗?
由於小 Z 好強,所以小 z 總是後手。

#include<cstdio>
struct edge{
    int to,nx;
}e[5000001];
int h[500001];
int n,Q,p;
int num;
int a[500001];
int fa[500001][21],dep[500001],l[500001],r[500001];
int BIT[500001];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==0)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10
+ch-0;ch=getchar();} return x*f; } void update(int x,int v){ for(int i=x;i<=n;i+=(i&(-i))){ BIT[i]^=v; } } int query(int x){ int ans=0; for(int i=x;i;i-=(i&(-i))){ ans^=BIT[i]; } return ans; } void ae(int fr,int to){ e[++p]=(edge){to,h[fr]};h[fr]=p; }
void dfs(int x){ for(int i=1;i<=20;i++){ if(dep[x]>=(1<<i)){ fa[x][i]=fa[fa[x][i-1]][i-1]; } else break; } l[x]=++num; for(int i=h[x];i;i=e[i].nx){ int v=e[i].to; if(v!=fa[x][0]){ dep[v]=dep[x]+1; fa[v][0]=x; dfs(v); } } r[x]=num; } int lca(int x,int y){ if(dep[x]<dep[y]){ int tm=x;x=y;y=tm; } int t=dep[x]-dep[y]; for(int i=0;i<=20;i++){ if((1<<i)&t) x=fa[x][i]; } for(int i=20;i>=0;i--){ if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; } if(x==y) return x; return fa[x][0]; } int main(){ //freopen("game.in","r",stdin); //freopen("game.out","w",stdout); n=read(); for(int i=1;i<=n;i++){ a[i]=read(); } for(int i=1;i<n;i++){ int x=read(),y=read(); ae(x,y);ae(y,x); } dfs(1); for(int i=1;i<=n;i++){ update(l[i],a[i]);update(r[i]+1,a[i]); } Q=read(); while(Q--){ char op[5]; scanf("%s",op); int x=read(),y=read(); if(op[0]==Q){ int LCA=lca(x,y); int sg=query(l[x])^query(l[y])^a[LCA]; if(sg) puts("Yes"); else puts("No"); } else{ update(l[x],a[x]);update(r[x]+1,a[x]); a[x]=y; update(l[x],y);update(r[x]+1,y); } } return 0; }

20170908 校內模擬賽 遊戲