JZOJ4759. 石子游戏
来源:互联网 发布:淘宝买家注册 编辑:程序博客网 时间:2024/06/05 17:05
题目大意
给定一棵
一开始每个结点有
操作有三种:
对于1操作的询问,两人在以
Data Constraint
题解
如果是在序列上做游戏,那么这个游戏就等价于每个结点石子数为
然后放到树上,就类似阶梯Nim游戏了。显然只有在到根距离为奇数的结点上做游戏才是有效的。
得到以上两条结论之后,现在问题就转化为询问子树内深度为奇数或者偶数的结点权值异或和。
因为有增加操作,所以考虑用Splay维护DFS序。
那么怎么找
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 100000 + 10int Node[2*N] , Next[2*N] , Head[N] , tot ;int Son[N][2] , Pre[N] , Val[N] , Deep[N] ;int Size[N] , OddXor[N] , AllXor[N] , MinDep[N] ;int A[N] , Dep[N] , D[N] ;int a[N] , dep[N] ;int n , m , t ;int Root , Cnt ;bool Check( int x ) { return x != 0 ;}void link( int u , int v ) { Node[++tot] = v ; Next[tot] = Head[u] ; Head[u] = tot ;}void DFS( int x , int F ) { D[++D[0]] = x ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F ) continue ; dep[Node[p]] = dep[x] + 1 ; DFS( Node[p] , x ) ; }}void Update( int now ) { int ls = Son[now][0] ; int rs = Son[now][1] ; MinDep[now] = min( Deep[now] , min( MinDep[ls] , MinDep[rs] ) ) ; OddXor[now] = OddXor[ls] ^ OddXor[rs] ^ ( (Deep[now] & 1) ? Val[now] : 0 ) ; AllXor[now] = AllXor[ls] ^ AllXor[rs] ^ Val[now] ; Size[now] = Size[ls] + Size[rs] + 1 ;}int Build( int l , int r , int Fa ) { if ( l > r ) return 0 ; int mid = (l + r) / 2 ; int now = D[mid] ; Pre[now] = Fa ; Val[now] = A[mid] ; Deep[now] = Dep[mid] ; Son[now][0] = Build( l , mid - 1 , now ) ; Son[now][1] = Build( mid + 1 , r , now ) ; Update( now ) ; return now ;}void Rotate( int x ) { int F = Pre[x] , G = Pre[F] ; int Side = Son[F][1] == x ; Pre[x] = G , Pre[F] = x ; Son[F][Side] = Son[x][!Side] ; Pre[Son[x][!Side]] = F ; Son[x][!Side] = F ; Son[G][Son[G][1]==F] = x ; Update(F) ; Update(x) ;}void Splay( int x , int Goal ) { while ( Pre[x] != Goal ) { int y = Pre[x] , z = Pre[y] ; if ( z != Goal ) { if ( (Son[y][0] == x) ^ (Son[z][0] == y) ) Rotate(x) ; else Rotate(y) ; } Rotate(x) ; } if ( !Goal ) Root = x ;}int Find( int x ) { if ( MinDep[Son[x][0]] <= Deep[Root] ) return Find(Son[x][0]) ; if ( Deep[x] <= Deep[Root] ) return x ; return Find(Son[x][1]) ;}int Query( int now ) { Splay( now , 0 ) ; int Rson = Find(Son[Root][1]) ; Splay( Rson , Root ) ; now = Son[Rson][0] ; if ( Deep[Root] & 1 ) return Check( AllXor[now] ^ OddXor[now] ) ; else return Check( OddXor[now] ) ;}void Modify( int now , int v ) { Splay( now , 0 ) ; Val[now] = v ; Update(now) ;}void Insert( int x , int y , int v ) { Deep[y] = Deep[x] + 1 ; Val[y] = v ; Splay( x , 0 ) ; Pre[y] = x ; Son[y][1] = Son[x][1] ; Son[x][1] = y ; Pre[Son[y][1]] = y ; Update(y) ; Update(x) ;}int main() { scanf( "%d%d" , &n , &m ) ; for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &a[i] ) ; for (int i = 1 ; i < n ; i ++ ) { int u , v ; scanf( "%d%d" , &u , &v ) ; link( u , v ) ; link( v , u ) ; } scanf( "%d" , &t ) ; dep[1] = 1 ; DFS( 1 , 0 ) ; D[++D[0]] = n + t + 1 ; A[n+t+1] = Dep[n+t+1] = 0 ; for (int i = 1 ; i <= D[0] ; i ++ ) { A[i] = a[D[i]] % (m + 1) ; Dep[i] = dep[D[i]] ; } memset( MinDep , 63 , sizeof(MinDep) ) ; Root = Build( 1 , n + 1 , 0 ) ; int Last = 0 ; for (int i = 1 ; i <= t ; i ++ ) { int op ; scanf( "%d" , &op ) ; if ( op == 1 ) { int v ; scanf( "%d" , &v ) ; v = v ^ Last ; if ( Query(v) ) printf( "Yes\n" ) , Last ++ ; else printf( "No\n" ) ; } else if ( op == 2 ) { int x , y ; scanf( "%d%d" , &x , &y ) ; x = x ^ Last ; y = y ^ Last ; Modify( x , y % (m + 1) ) ; } else { int u , v , x ; scanf( "%d%d%d" , &u , &v , &x ) ; u = u ^ Last ; v = v ^ Last ; x = x ^ Last ; Insert( u , v , x % (m + 1) ) ; } } return 0 ;}
以上.
1 0
- JZOJ4759. 石子游戏
- [BZOJ3729]Gty的游戏/[JZOJ4759]石子游戏
- 石子游戏
- 石子游戏
- 石子游戏
- 石子游戏
- 石子游戏
- "取石子"游戏
- 取石子游戏
- 取石子游戏
- 取石子游戏
- POJ1067取石子游戏
- PKU1067 取石子游戏
- 取石子游戏
- 取石子游戏
- 1067 取石子游戏
- PKU1067(取石子游戏)
- 1281 堆石子游戏
- Java死锁的排查
- 17. Letter Combinations of a Phone Number
- 图解Windows域的命令行操作
- Android碎片 -- Fragment
- Web——Servlet操作Cookie
- JZOJ4759. 石子游戏
- ArryFilter过滤ListView
- POI
- 抽象类与接口的区别
- 问题集合
- bzoj 3262: 陌上花开(cdq分治)
- hdoj3665【简单DFS】
- HTML中遇到的那些方法(1)
- 371 Sum of Two Integers