codeforces 812E

来源:互联网 发布:js判断哪个tr被双击 编辑:程序博客网 时间:2024/05/28 05:15
思路有了,占坑,做完来写想了很久的题主要纠结的是树上的操作怎么影响先后输赢,后来先发现了叶节点的上一层节点的先后是必抢的(必胜状态),这个节点又是由上一层节点决定,于是想到了奇书层或者偶数层的结点是要满足nim博弈的,想到这边差不多可以做了。
#include<stdio.h>#include<algorithm>#include<math.h>#include<stdlib.h>#include<map>#include<vector>using namespace std;typedef long long ll;int n;#define maxn 100010int a[maxn];vector <ll> g[maxn];ll num;ll l[maxn];int it[maxn];map <ll,ll> p;map <ll,ll> q;ll lmax ( ll a, ll b){    if (a>b)return a;    else return b;}void dfs (int v,int level ){    l[v]=level;    int i;    num = lmax (num ,level);    for (i=0;i<g[v].size ();i++){        int u = g[v][i];        if (!u) continue;        dfs (u,level+1);    }    return ;}int main (){    int i;    scanf ("%d",&n);    for (i=1;i<=n;i++){        scanf ("%d",&a[i]);        it[i]=a[i];    }    for (i=2;i<=n;i++){        int f;        scanf("%d",&f);        g[f].push_back (i);    }    num = 0;    dfs (1,1);    //for (i=1;i<=n;i++){        //printf("%d %d\n",a[i],l[i]);//    /}  //  printf ("%d\n",num);    int pp = num %2;    ll ans =0;    ll oddnum = 0,rnum=0;    sort (a+1,a+1+n);    int len = unique (a+1,a+1+n)-(a+1) ;    for (i=1;i<=n;i++){        if (l[i]%2==pp){            ans ^= it[i];            p[it[i]]++;        }        else q[it[i]]++;        if (l[i]%2==1) {oddnum++;        }        else {rnum ++ ;}    }    //printf("%d\n",ans);    //for (i=1;i<=len;i++){        //if (q[a[i]])       // printf("%d %d\n",a[i],q[a[i]]);    //}    if (!ans){        ll temp =ans;        ans = oddnum *(oddnum-1)/2 + rnum*(rnum-1)/2;        for (i=1;i<=len;i++){            ans += p[a[i]]*q[a[i]] ;        }        printf("%lld\n", ans);    }    else {        ll temp = ans;        //printf("%lld\n",temp);        ans = 0;        for (i=1;i<=n;i++){            if (l[i]%2==pp){                //printf("%d %lld\n",it[i],temp^it[i]);                ans += q[temp^it[i]];            }        }        printf("%lld\n", ans);    }}