Codeforces Round #706 (Div. 2)-D. Let's Go Hiking 题解

题目传送门

解题思路:

  从两个人能够选择的点来看,\(Qingshan\)要走的是上升序列,\(Daniel\)要走的是下降序列。所以如果\(Qingshan\)要取得胜利的话,就必须要在上升序列的顶峰处开始往低处走,并且能比\(Daniel\)走的步数多或者挡住\(Daniel\)的下一步。两个人的最优选项都是走尽可能多次或者可以挡住对方。注意\(Qingshan\)不能从\(1\)或者\(n\)开始走,否则\(Daniel\)选择\(2\)或者\(n-1\)即可获胜。
  接下来我们就需要记录下最长上升序列和下降序列的长度\(len\),同时记录一下这样的序列个数\(num\)。并且我们能会发现,\(len\)至少为2,\(num\)至少为1。
  假设一开始\(Qingshan\)开始的位置为\(x\),序列开始的位置为\(s\),我们会发现\(Qingshan\)必须要从\(x=s+len-1\)开始走,如果不是的话,\(Daniel\)可以直接选在\(x-1\)处(上升)或者\(x+1\)处(下降),这样\(Qingshan\)就会直接输掉。
  如果这样的序列个数大于\(2\),那么\(Qingshan\)一定会输,因为\(Daniel\)可以走\(len\)步,但是\(Qingshan\)最多只能走\(len\)步,并且\(Qingshan\)是先手。
  如果只有\(1\)个这样的序列,我们就需要对序列长度的奇偶性进行讨论:
   ①\(len\)是偶数。由于\(Qingshan\)开始的位置只能是\(s+len-1\),所以\(Daniel\)在这样的情况下总是可以挡住\(Qingshan\)的下一步,比如从\(s\)开始走,所以这种情形下\(Qingshan\)一定是输的。
   ②\(len\)是奇数。和偶数的情况一样,\(Daniel\)总是可以挡住\(Qingshan\),所以这种情形下\(Qingshan\)一定是输的。
  如果有两个这样的序列,我们只需要比较一下上升序列和下降序列的长度,只有上升序列长度等于下降序列长度且长度都为奇数,\(Qingshan\)才能获胜。
  总结发现,如果序列长度是偶数的话,直接输出\(0\)即可。

代码:

#include<cstdio>
#include<iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;

const int N = 100005;

int h[N];
int up[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> h[i];
    for (int i = 2; i <= n; i++) up[i] = (h[i] > h[i - 1]) ? 1 : 0;

    int len = 0, num = 0;
    int l, r;
    for (l = 2, r = 2; l <= n; )
    {
        int st = up[l];
        while (r + 1 <= n && st == up[r + 1]) r++;
        int tlen = r - l + 2;
        if (tlen > len)
        {
            len = tlen;
            num = 1;
        }
        else if (tlen == len) num++;
        l = r = r + 1;
    }

    if (num != 2 || (len & 1) == 0) cout << 0 << endl;
    else
    {
        int isWin = 0;
        for (int i = 3; i <= n; i++)
        {
            if (up[i - 1] && !up[i])
            {
                int l = i - 1, r = i;
                while (l - 1 >= 1 && up[l - 1]) l--;
                while (r + 1 <= n && !up[r + 1]) r++;
                if ((r - i + 1)+1 ==len&& (i-1)-(l-1)+1 ==len)
                {
                    isWin = 1;
                    break;
                }
            }
        }
        cout << isWin << endl;
    }
    return 0;
}
posted @ 2021-03-11 20:21  Daneii  阅读(61)  评论(0编辑  收藏  举报