题解:Luogu P11385 Walki robotów

题目大意

原题链接:P11385 Walki robotów

\(n\) 个机器人,编号从 \(1\)\(n\)。第 \(i\) 个机器人有两个参数 \(s_{i}\)\(z_{i}\ (1 \leq s_{i}, z_{i} \leq n)\),而所有机器人的 \(s_{i}\)\(z_{i}\) 都各不相同。

对于两个尚未被淘汰的机器人 \(i\)\(j\),如果 \(s_{i}>s_{j}\)\(z_{i}>z_{j}\),那么第 \(i\) 个机器人将淘汰第 \(j\) 个机器人。如果 \(s_{i}<s_{j}\)\(z_{i}<z_{j}\),那么第 \(j\) 个机器人将淘汰第 \(i\) 个机器人。如果出现一大一小的情况就意味着两个机器人同归于尽。

你需要做出一系列比赛安排使得机器人全部被淘汰。

解题思路

贪心的思想我们很容易想到先把那些可以被单独淘汰的机器人先淘汰掉,那么剩下来的机器人们只会是两两同归于尽,没有办法单独淘汰对手,那如果此时剩下的机器人是偶数个,那么让他们两两比赛就可以满足全淘汰的要求。而难点是如果剩下的个数是奇数怎么办?

我们可能会想到从那些已经被单独淘汰的机器人中找一个可以跟剩下的任意一个机器人同归于尽的,把剩下的机器人淘汰掉一只,使其变为偶数,而我们如何判断有没有这样的机器人存在呢?

答案就是判断剩下的机器人中两个属性的最小值的情况,怎么个判断法?我们先把两个最小属性值 \(m1\)\(m2\) 找出来,如果不满足 \(m1=m2=n-cnt+1\),那么就存在符合上述需求的机器人(\(cnt\) 是剩下机器人的个数)。因为如果满足 \(m1=m2=n-cnt+1\) 的话,就证明淘汰的那 \(i\) 个机器人每个的两个属性值都不会大于 \(i\),也就是剩下的机器人中随便一个机器人的属性都比所有淘汰掉的机器人大,自然就不满足一开始的需求了,此时就是无解的情况。

参考代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
struct rb {
  ll s, z;
} g[N], q[N];
bool st[N];
bool cmp(rb &a, rb &b) { return a.s > b.s; }

int main() {
  ll n, cnt = 0;
  cin >> n;
  for (int i = 1; i <= n; i++) cin >> g[i].s >> g[i].z;
  sort(g + 1, g + n + 1, cmp);
  for (int i = 1; i < n; i++) {
    if (st[i]) continue;  // 如果该机器人已经被它前面的淘汰了,就直接跳过
    for (int j = i + 1; j <= n; j++) {
      if (g[i].z > g[j].z) st[j] = true;
      else break;
    }
    q[++cnt] = g[i];
  }
  if (!st[n]) q[++cnt] = g[n];
  ll m1 = 1e12, m2 = 1e12;
  for (int i = 1; i <= cnt; i++) 
    m1 = min(m1, q[i].s), m2 = min(m2, q[i].z);
  if (cnt % 2 == 0 || !(m1 == m2 && m1 == n - cnt + 1))
    cout << "TAK" << endl;
  else
    cout << "NIE" << endl;
  return 0;
}
posted @ 2025-02-17 20:54  Duanhen  阅读(32)  评论(0)    收藏  举报