G winner
题意
n
n
n个人参加竞技比赛
比赛由三种模式,每种模式,
n
n
n个人有不同得能力值
举行
n
−
1
n-1
n−1场比赛,每场比赛选择两个人决斗,能力值低的人淘汰
q
q
q个询问,返回该角色是否有可能生存到最后
分析
容易想到任意场的最强者一定是可能生存到最后的
若场数足够,能在其他两场打败该场最强者的人,可能生存到最后(即最强者打败除该人以外所有人,该者最后打败最强者)
1
,
2
,
3
,
4
,
5
1,2,3,4,5
1,2,3,4,5
1
,
2
,
3
,
5
,
4
1,2,3,5,4
1,2,3,5,4
由5打败1,2,3,最后4打败5
若场数足够,能打败(能打败最强者的人),也有可能生存到最后
1
,
2
,
3
,
4
,
5
1,2,3,4,5
1,2,3,4,5
1
,
2
,
3
,
5
,
4
1,2,3,5,4
1,2,3,5,4
1
,
2
,
4
,
5
,
3
1,2,4,5,3
1,2,4,5,3
由5打败1,2,再由4打败5,最后由3打败4
依次类推,逐步递推,寻找能够打败前者的人。
先对三种模式能力离散化,
再预处理后缀和,便于下面递推
代码
后缀和处理
先预处理出第i场排名第i的人,另外两场的排名
再处理第i-n场中,在另外两场的最低排名
//预处理出第i场排名第i的人,另外两场的排名
for (int i = 1; i <= n; i++) {
num1[a[1][i]].second = a[2][i]; num1[a[1][i]].third = a[3][i];
num2[a[2][i]].first = a[1][i]; num2[a[2][i]].third = a[3][i];
num3[a[3][i]].first = a[1][i]; num3[a[3][i]].second = a[2][i];
}
//处理第i-n场中,在另外两场的最低排名
m1[n + 1][2] = m1[n + 1][3] =
m2[n + 1][1] = m2[n + 1][3] =
m3[n + 1][1] = m3[n + 1][2] = inf;
for (int i = n; i >= 1; i--) {
m1[i][2] = min(m1[i + 1][2], num1[i].second);
m1[i][3] = min(m1[i + 1][3], num1[i].third);
m2[i][1] = min(m2[i + 1][1], num2[i].first);
m2[i][3] = min(m2[i + 1][3], num2[i].third);
m3[i][1] = min(m3[i + 1][1], num3[i].first);
m3[i][2] = min(m3[i + 1][2], num3[i].second);
}
递推
初始在每场排名最低限制为n-1(排名在第i场在
m
i
n
[
i
]
min[i]
min[i]以上是可能赢得人)
每次递推推出能打败每场最低限制的人,在其他两场的最低排名
int min1 = n - 1, min2 = n - 1, min3 = n - 1,
pre1 = inf, pre2 = inf, pre3 = inf;
for (int i = 1; i < n; i++) {
pre2 = min(pre2, m1[min1 + 1][2]); pre3 = min(pre3, m1[min1 + 1][3]);
pre1 = min(pre1, m2[min2 + 1][1]); pre3 = min(pre3, m2[min2 + 1][3]);
pre1 = min(pre1, m3[min3 + 1][1]); pre2 = min(pre2, m3[min3 + 1][2]);
min1 = min(min1, pre1);
min2 = min(min2, pre2);
min3 = min(min3, pre3);
}
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 100005;
const int inf = 1e9;
struct Node
{
int first;
int second;
int third;
}num1[maxn], num2[maxn], num3[maxn];
int a[4][maxn], m1[maxn][4], m2[maxn][4], m3[maxn][4];
bool vis[maxn];
pii p[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, q;
cin >> n >> q;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= n; j++)
p[j] = pii(a[i][j], j);
sort(p + 1, p + 1 + n);
for (int j = 1; j <= n; j++)
a[i][p[j].second] = j;
}
for (int i = 1; i <= n; i++) {
num1[a[1][i]].second = a[2][i]; num1[a[1][i]].third = a[3][i];
num2[a[2][i]].first = a[1][i]; num2[a[2][i]].third = a[3][i];
num3[a[3][i]].first = a[1][i]; num3[a[3][i]].second = a[2][i];
}
m1[n + 1][2] = m1[n + 1][3] =
m2[n + 1][1] = m2[n + 1][3] =
m3[n + 1][1] = m3[n + 1][2] = inf;
for (int i = n; i >= 1; i--) {
m1[i][2] = min(m1[i + 1][2], num1[i].second);
m1[i][3] = min(m1[i + 1][3], num1[i].third);
m2[i][1] = min(m2[i + 1][1], num2[i].first);
m2[i][3] = min(m2[i + 1][3], num2[i].third);
m3[i][1] = min(m3[i + 1][1], num3[i].first);
m3[i][2] = min(m3[i + 1][2], num3[i].second);
}
int min1 = n - 1, min2 = n - 1, min3 = n - 1,
pre1 = inf, pre2 = inf, pre3 = inf;
for (int i = 1; i < n; i++) {
pre2 = min(pre2, m1[min1 + 1][2]); pre3 = min(pre3, m1[min1 + 1][3]);
pre1 = min(pre1, m2[min2 + 1][1]); pre3 = min(pre3, m2[min2 + 1][3]);
pre1 = min(pre1, m3[min3 + 1][1]); pre2 = min(pre2, m3[min3 + 1][2]);
min1 = min(min1, pre1);
min2 = min(min2, pre2);
min3 = min(min3, pre3);
}
for (int i = 1; i <= n; i++) {
if (a[1][i] > min1)vis[i] = true;
if (a[2][i] > min2)vis[i] = true;
if (a[3][i] > min3)vis[i] = true;
}
int x;
while (q--) {
cin >> x;
if (vis[x])cout << "YES\n";
else cout << "NO\n";
}
}