Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree (树上尼姆博弈)

来源:互联网 发布:西南大学远程网络教育 编辑:程序博客网 时间:2024/05/16 08:49
E. Sagheer and Apple Tree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Sagheer is playing a game with his best friend Soliman. He brought a tree with n nodes numbered from 1 to n and rooted at node 1. The i-th node has ai apples. This tree has a special property: the lengths of all paths from the root to any leaf have the same parity (i.e. all paths have even length or all paths have odd length).

Sagheer and Soliman will take turns to play. Soliman will make the first move. The player who can't make a move loses.

In each move, the current player will pick a single node, take a non-empty subset of apples from it and do one of the following two things:

  1. eat the apples, if the node is a leaf.
  2. move the apples to one of the children, if the node is non-leaf.

Before Soliman comes to start playing, Sagheer will make exactly one change to the tree. He will pick two different nodes u and v and swap the apples of u with the apples of v.

Can you help Sagheer count the number of ways to make the swap (i.e. to choose u and v) after which he will win the game if both players play optimally? (u, v) and (v, u) are considered to be the same pair.

Input

The first line will contain one integer n (2 ≤ n ≤ 105) — the number of nodes in the apple tree.

The second line will contain n integers a1, a2, ..., an (1 ≤ ai ≤ 107) — the number of apples on each node of the tree.

The third line will contain n - 1 integers p2, p3, ..., pn (1 ≤ pi ≤ n) — the parent of each node of the tree. Node i has parent pi (for 2 ≤ i ≤ n). Node 1 is the root of the tree.

It is guaranteed that the input describes a valid tree, and the lengths of all paths from the root to any leaf will have the same parity.

Output

On a single line, print the number of different pairs of nodes (u, v)u ≠ v such that if they start playing after swapping the apples of both nodes, Sagheer will win the game. (u, v) and (v, u) are considered to be the same pair.

Examples
input
32 2 31 1
output
1
input
31 2 31 1
output
0
input
87 2 2 5 4 3 1 11 1 1 4 4 5 6
output
4
Note

In the first sample, Sagheer can only win if he swapped node 1 with node 3. In this case, both leaves will have 2 apples. If Soliman makes a move in a leaf node, Sagheer can make the same move in the other leaf. If Soliman moved some apples from a root to a leaf, Sagheer will eat those moved apples. Eventually, Soliman will not find a move.

In the second sample, There is no swap that will make Sagheer win the game.

Note that Sagheer must make the swap even if he can win with the initial tree.


题目大意:有一颗苹果树,每个结点上有一定量的苹果,现在有两个人轮流进行操作,操作方式有两种,第一种,吃掉叶子结点上的若干苹果(必须吃) 第二种,将非叶子结点的若干苹果移动到它的儿子结点上(必须移动)。吃掉最后一个苹果的人获胜。 现在给予后手一个在开始游戏前可以交换结点的权利,问有多少种交换方式可以使得后手必胜。

分析: 因为所有叶子结点的深度同奇偶,所以有这么两种情况。

第一种,先手移动k个苹果到儿子,那么后手也可以将这k个移动到它的儿子,并且最后不能移动的时候后手可以将它吃掉。那么这一系列操作得到的是,整棵数失去了这k个苹果,但是没有改变的是与失去这k个苹果深度奇偶不一样的所有节点的苹果必定不改变,而且先手人也不变。那么对于先手来说这个结点对于改变局势是没有用的。

第二种,就是与上面那种结点深度奇偶不一样的结点,这种结点的个数对于先手局势是有影响的,当将这上面的苹果移动到它的儿子的时候,这些苹果也就变得没有意义了(对于先手相当于已经吃掉了),所以就变成了裸的尼姆博奕。

当没改变的时候所有第二种情况里面的结点的亦或为0。那么答案就是 第一种深度任意选两个交换+第二种深度任意选两个交换+交换第一和第二苹果数相同的结点。(a^b=b^a);

当不为0的时候,说明先手必胜,那么就要使得交换后能变成亦或为0,所以必须第一种和第二种互换才能有机会达成,又因为 a^b^b=a。所以交换后其实就是 a^b^b^a=0,所以在第二种里面找结点(假设有k个苹果,且之前的所有亦或值为xor),然后查看第一种深度里面是否存在 k^xor个苹果的结点 。


AC代码

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<map>using namespace std;long long a[200000];long long dep[200000];vector<long long>v[200000];map<long long,long long>q1,q2,vis;long long mxdp;void bulidtree(long long u,long long pre,long long t){dep[u]=t;mxdp=max(mxdp,t);for(int i=0;i<v[u].size();i++){if(v[u][i]!=pre)bulidtree(v[u][i],u,t+1);}}int main(){int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);mxdp=0;for(int i=2;i<=n;i++){int u;scanf("%d",&u);v[u].push_back(i);v[i].push_back(u);}bulidtree(1,-1,1);long long xorr=0;long long numq1=0,numq2=0;for(int i=1;i<=n;i++){if(mxdp%2==dep[i]%2){xorr^=a[i];q1[a[i]]++;numq1++;}elseq2[a[i]]++,numq2++;}long long ans=0;vis.clear();if(!xorr){ans+=numq1*(numq1-1)/2+numq2*(numq2-1)/2;for(int i=1;i<=n;i++){if(!vis[a[i]]){ans+=q1[a[i]]*q2[a[i]];vis[a[i]]=1;}}printf("%lld\n",ans);}else{for(int i=1;i<=n;i++){if(mxdp%2==dep[i]%2)ans+=q2[a[i]^xorr];}printf("%lld\n",ans);}}


阅读全文
0 0
原创粉丝点击