Codeforces Round #706 B. Let‘s Go Hiking(博弈)

3 篇文章 0 订阅

B. Let’s Go Hiking

题意

有一个长度为 n n n 的排列。首先Qingshan选择一个数 a a a ,Daniel选择另一个数 b b b

Qingshan先手,每次移动到相邻的数 a ′ ( a ′ < a , a ′ ! = b ) a'(a'<a,a'!=b) a(a<a,a!=b),然后Daniel移动到相邻的数 b ′ ( b ′ > b , b ′ ! = a ) b'(b'>b,b'!=a) b(b>b,b!=a)

问Qingshan初始有多少种选择可以必胜。

题解
  • 把这个排列分割成若干单调区间;
  • Qingshan选择的数一定在一个最长的单调区间上,否则Daniel可以选择一个更长单调区间的端点;
  • 由于是Qingshan先选择且先手,如果只有一个最长的单调区间,Daniel可以后手选择一个位置来保证必胜,如果有大于2个最长的单调区间,那么两个人可以走相同的距离,后手必胜;
  • 所以必须两个人选择同一个单调区间的两个端点相互靠近,并且区间的长度为奇数可以保证必胜;
  • 答案只有可能为 0/1。
代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#pragma endregion
const int maxn = 2e5 + 5;
int n;
ll a[maxn];
vector<pair<ll, ll>> id;
bool check() {
    if (id.size() != 2) return 0;
    int l1 = id[0].first, r1 = id[0].second;
    int l2 = id[1].first, r2 = id[1].second;
    return r1 == l2 && a[r1] > a[l1] && a[l2] > a[r2] && (r1 - l1) % 2 == 0;
}
int main() {
    scanf("%d", &n);
    rep(i, 1, n) scanf("%lld", &a[i]);
    int maxx = 0;
    for (int l = 1, r = 2; r <= n; l = r, r = r + 1) {
        while (r + 1 <= n && (a[r + 1] - a[r]) * (a[r] - a[l]) > 0) ++r;
        if (r - l + 1 >= maxx) {
            if (r - l + 1 > maxx) id.clear(), maxx = r - l + 1;
            id.push_back({l, r});
        }
    }
    puts(check() ? "1" : "0");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值