zoukankan      html  css  js  c++  java
  • CodeForces 812E Sagheer and Apple Tree 阶梯博弈

    CodeForces 812E

    题意: 一棵以点 1 为根的树,每个点上有 ai 个苹果,两个人轮流操作。  每次操作:选择一个非空的点,如果这个点是叶子结点,则可以吃掉这个点上任意个苹果;如果这个点不是叶子结点,则可以选择这个点上任意个苹果移动到它的一个儿子结点上。   但后手在游戏开始前可以交换任意两个点的苹果,问后手有多少种交换方案可以获胜。  (题目保证所有叶子结点到根结点路径长度的奇偶性相同)

    tags: 就是阶梯博弈,所有点按到根结点路径长度奇偶性分两类,第一类与叶子结点奇偶性相同,第二类与叶子结点不同。 只要 dfs 求出第一类点的异或和,然后枚举即可。

    // 812E
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 100005;
    
    ll  ans;
    int n, a[N], pi;
    vector<int > G[N];
    int s[2], flag, cnt[2];
    map<int , int > mp[2];
    void upd(int u, int dep)
    {
        if((dep%2) != (flag%2))
        {
            s[flag^1]^=a[u];
            mp[flag^1][a[u]]++;
            ++cnt[flag^1];
        }
        else
        {
            s[flag]^=a[u];
            mp[flag][a[u]]++;
            ++cnt[flag];
        }
    }
    void dfs(int u, int fa, int dep)
    {
        if(G[u].size()==1 && u!=1)
        {
            if((dep&1) && flag==0) flag^=1;
        }
        for(auto to : G[u])
            if(to!=fa)
                dfs(to, u, dep+1);
        upd(u, dep);
    }
    int main()
    {
        scanf("%d", &n);
        rep(i,1,n) scanf("%d", &a[i]);
        rep(i,2,n)
        {
            scanf("%d", &pi);
            G[pi].PB(i);
            G[i].PB(pi);
        }
        dfs(1, 0, 0);
        if(s[flag]==0)
        {
            if(cnt[flag]>1) ans += 1LL*cnt[flag]*(cnt[flag]-1)/2;
            if(cnt[flag^1]>1)  ans += 1LL*cnt[flag^1]*(cnt[flag^1]-1)/2;
            for(auto it=mp[flag].begin(); it!=mp[flag].end(); ++it)
            {
                int tmp1=it->fi, tmp2=it->se, tmp3=mp[flag^1][tmp1];
                ans += 1LL*tmp2*tmp3;
            }
        }
        else
        {
            for(auto it=mp[flag].begin(); it!=mp[flag].end(); ++it)
            {
                int tmp1=it->fi, tmp2=it->se, tmp3=mp[flag^1][s[flag]^tmp1];
                ans += 1LL*tmp2*tmp3;
            }
        }
        printf("%lld
    ", ans);
    
        return 0;
    }
  • 相关阅读:
    $NOIp2018$劝退记
    Markdown 使用技巧
    【题解】 bzoj2462: [BeiJing2011]矩阵模板
    【总结】字符串hash
    【题解】 bzoj3555: [Ctsc2014]企鹅QQ (字符串Hash)
    【题解】 bzoj3916: [Baltic2014]friends (字符串Hash)
    【题解】 bzoj2982: combination (Lucas定理)
    【题解】 bzoj1135: [POI2009]Lyz (线段树+霍尔定理)
    【题解】 bzoj3693: 圆桌会议 (线段树+霍尔定理)
    【题解】 AtCoder ARC 076 F
  • 原文地址:https://www.cnblogs.com/sbfhy/p/7688245.html
Copyright © 2011-2022 走看看