zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    LeetCode Best Time to Buy and Sell Stock
    LeetCode Scramble String
    LeetCode Search in Rotated Sorted Array II
    LeetCode Gas Station
    LeetCode Insertion Sort List
    LeetCode Maximal Rectangle
    Oracle procedure
    浏览器下载代码
    Shell check IP
    KVM- 存储池配置
  • 原文地址:https://www.cnblogs.com/mollnn/p/14541599.html
Copyright © 2011-2022 走看看