• Codeforces Round #417 (Div. 2) 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
    3
    2 2 3
    1 1
    output
    1
    input
    3
    1 2 3
    1 1
    output
    0
    input
    8
    7 2 2 5 4 3 1 1
    1 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.

    这个题就非常好,补齐了我sg函数的一部分知识

    之前我应该是见过类似的题的,但我记不清了,并没有写出来

    慢慢分析这道题

    先考虑全是叶子的情况,那就是一个最普通的nim游戏,所有叶子的苹果数量异或起来即可

    然后我们考虑这样一个游戏

    n堆石子排成一列,你可以做两种操作

    1、某堆石子(除了最右面一堆)里拿一些出来,放到它右边的堆里

    2、从最右边的一堆里丢到若干个石子

    这个要怎么弄呢?

    有趣的部分来了,我们考虑给最基础的nim游戏加上一条规则:你可以给某一堆石子加上若干个石子,加石子的数量有限制,假设不会出现死循环

    经过一些尝试后,你会发现,这条规则是完全无用的

    为什么?因为原来的获胜方才有办法利用这条规则,原来的失败方如果使用了这条规则,获胜方可以立刻取消掉这次操作

    联想到这个性质,我们可以对刚才的游戏做一些改动

    把石子堆黑白染色,最右边一堆为白堆,然后白黑相间,最终的sg函数是所有白堆的石子数的异或和

    为什么呢?因为如果你使用了一次从黑到白的移动,对方可以使用一次相应操作来抵消你这次操作的影响,比如一共三堆石子,你从第二堆里拿了3个放到第三堆,对方就可以从第三堆里拿出3个丢掉,这样所有白堆的状态都没有变

    于是乎,原题的做法也呼之欲出了,把树分层染色,叶子为白色,最终的sg函数即为所有白色节点的苹果数量异或和

    然后如果初始状态是0,那允许的操作有:

    1、交换两个白点

    2、交换两个黑点

    3、交换一对苹果数量相同的白点和黑点

    如果初始状态不是0,那只能交换一个白点和一个能使结果为0的黑点

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <map>
      9 #include <stack>
     10 #include <set>
     11 #include <vector>
     12 #include <queue>
     13 #include <time.h>
     14 #define eps 1e-7
     15 #define INF 0x3f3f3f3f
     16 #define MOD 1000000007
     17 #define rep0(j,n) for(int j=0;j<n;++j)
     18 #define rep1(j,n) for(int j=1;j<=n;++j)
     19 #define pb push_back
     20 #define set0(n) memset(n,0,sizeof(n))
     21 #define ll long long
     22 #define ull unsigned long long
     23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
     24 #define max(a,b) (a>b?a:b)
     25 #define min(a,b) (a<b?a:b)
     26 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
     27 #define TO(j) printf(#j": %d
    ",j);
     28 //#define OJ
     29 using namespace std;
     30 const int MAXINT = 100010;
     31 const int MAXNODE = 100010;
     32 const int MAXEDGE = 2 * MAXNODE;
     33 char BUF, *buf;
     34 int read() {
     35     char c = getchar(); int f = 1, x = 0;
     36     while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
     37     while (isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
     38     return f * x;
     39 }
     40 char get_ch() {
     41     char c = getchar();
     42     while (!isalpha(c)) c = getchar();
     43     return c;
     44 }
     45 //------------------- Head Files ----------------------//
     46 struct edge {
     47     int u, v;
     48     edge *nxt;
     49     edge(int _u, int _v, edge *_nxt): u(_u), v(_v), nxt(_nxt) {}
     50     edge() {}
     51 } mp[MAXINT], *head[MAXINT];
     52 int cnt;
     53 void addedge(int u, int v) {
     54     mp[cnt] = edge(u, v, head[u]);
     55     head[u] = &mp[cnt++];
     56 }
     57 int dep[MAXINT], a[MAXINT], cnt_r[10000001], cnt_b[10000001], b, nob, nor;
     58 int fa[MAXINT], n, maxd, ans = 0;
     59 void dfs(int p) {
     60     maxd = max(maxd, dep[p]);
     61     iter(i, p) {
     62         dep[i->v] = dep[p] + 1;
     63         dfs(i->v);
     64     }
     65     if ((dep[p] & 1) == (maxd & 1)) {
     66         ans ^= a[p];
     67         cnt_b[a[p]]++;
     68         nob++;
     69     } else {
     70         cnt_r[a[p]]++;
     71         nor++;
     72     }
     73 }
     74 void get_input();
     75 void work();
     76 int main() {
     77     get_input();
     78     work();
     79     return 0;
     80 }
     81 void work() {
     82     dep[1] = 1;
     83     dfs(1);
     84     ll cnt_p = 0;
     85     if (ans == 0) {
     86         cnt_p = (ll)(nor) * (nor - 1) / 2 + (ll)(nob) * (nob - 1) / 2;
     87         rep1(i, n) {
     88             if((dep[i]&1)!=(maxd&1)) continue;
     89             cnt_p+=cnt_r[a[i]];
     90         }
     91     }else{
     92         rep1(i, n) {
     93             if((dep[i]&1)!=(maxd&1)) continue;
     94             if((ans^a[i])<=10000000) cnt_p+=cnt_r[ans^a[i]];
     95         }
     96     }
     97     printf("%lld
    ",cnt_p);
     98 }
     99 void get_input() {
    100     n = read();
    101     rep1(i, n) {
    102         a[i] = read();
    103     }
    104     for (int i = 2; i <= n; i++) {
    105         fa[i] = read();
    106         addedge(fa[i], i);
    107     }
    108 }
  • 相关阅读:
    c++ 左值和右值
    C++的顶层const和底层const的理解
    TCP/IP模型中的网络层
    有关TCP/IP模型中的网络接入层
    计算机网络协议与IPv4地址
    浅析计算机网络
    海思Android开发平台如何自定义update.zip内容
    Android平台RTL蓝牙适配偶现打不开问题调试笔记
    Android的SoundPool
    Android开发之IntentService
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6934522.html
Copyright © 2020-2023  润新知