• [CF1495B] Let's Go Hiking


    [CF1495B] Let's Go Hiking - 博弈

    Description

    两个人(下简称 QD )取爬山,一个长度为 (n) 的排列,其中 (p_i) 表示 (i) 处的高度。

    Q 会先选择一个位置 (x_0) ,并把这个位置告诉 D 。在此之后,D 会选择一个位置 (y_0)

    接下来两个人开始轮流爬山, Q 先行动。

    • 如果是 Q 行动,假设此时她在 (x) 处,D(y) 处,则她下一步移动到的位置 (x') 必须满足 (1le x'le n , |x'-x|=1 , x' eq y , p_{x'}<p_x)
    • 如果是 D 行动,假设此时他在 (y) 处,Q(x) 处,则他下一步移动到的位置 (y') 必须满足 (1le y'le n , |y'-y|=1 , y' eq x , p_{y'}>p_y)

    当某一个人不能行动时,对方获胜。求出 Q 能选出多少个初始位置 (x_0) ,保证她必胜。

    Solution

    x 必须选在坡顶,否则没救
    必须是双边的坡顶
    后手可以选这个坡上,与先手距离为奇数的位置,而偶数的位置是不可选的
    此时先手可以逃向另一边,如果另一边的距离小于等于这个位置,那么先手被堵死了
    所以,如果两边的距离都是奇数,先手死了
    如果两边距离一个奇数一个偶数,偶数比奇数小,还是先手死;偶数比奇数大,一样是先手死
    如果两边距离都是偶数,那么先手一定能逃脱,所以这时候就不能这么玩
    后手必须要去找控制区间之外的部分,找最大上升
    如果这个最大上升大于等于那个偶数,那么后手胜利

    因此,A 选择的,必然是

    • 两边距离相等且为偶数的(否则后手可以从长的那边堵死)
    • 距离最长且不能有第三次相等长度的出现的(否则后手可以模仿他对称着走)
    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int n, a[N], lu[N], ld[N], ru[N], rd[N], mlu[N], mru[N];
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
    
        for (int i = 2; i <= n; i++)
            if (a[i - 1] < a[i])
                ld[i] = ld[i - 1] + 1;
        for (int i = 2; i <= n; i++)
            if (a[i - 1] > a[i])
                lu[i] = lu[i - 1] + 1;
        for (int i = n - 1; i >= 1; i--)
            if (a[i + 1] < a[i])
                rd[i] = rd[i + 1] + 1;
        for (int i = n - 1; i >= 1; i--)
            if (a[i + 1] > a[i])
                ru[i] = ru[i + 1] + 1;
    
        int ans = 0;
        int mm = 0;
        int mc = 0;
        for (int i = 1; i <= n; i++)
        {
            if (lu[i] > mm)
                mm = lu[i], mc = 1;
            else if (lu[i] == mm)
                mc++;
            if (ld[i] > mm)
                mm = ld[i], mc = 1;
            else if (ld[i] == mm)
                mc++;
        }
    
        for (int i = 2; i < n; i++)
        {
            if (a[i - 1] < a[i] && a[i + 1] < a[i])
            {
                if (ld[i] % 2 == 0 && rd[i] % 2 == 0 && ld[i] == rd[i] && ld[i] == mm && mc == 2)
                {
                    ans++;
                }
            }
        }
    
        cout << ans << endl;
    }
    
  • 相关阅读:
    C#异步和多线程以及Thread、ThreadPool、Task区别和使用方法
    C# LINQ查询表达式用法对应Lambda表达式
    C# WPF 通过委托实现多窗口间的传值
    C# WPF 父控件通过使用可视化树找到子控件
    OpenCV打开摄像头闪退问题
    C#调用pyd
    微信支付(JSAPI、小程序)开发流程记录
    在安装pymysql遇到的问题
    个人理解的python的面向对象
    关于python3.4 MD5
  • 原文地址:https://www.cnblogs.com/mollnn/p/14541599.html
Copyright © 2020-2023  润新知