校内模拟赛 T1 合影

题目描述

好久没在这里写过链接之外的东西了

给定两个长度为 $n$ 的序列 $a,b$,序列中的每个数有两个属性 $v,k$

要求将 $a,b$ 重新排序,要求是一个序列内必须保证 $b$ 不降,且同一个位置 $b$ 的 $v$ 要大于 $a$ 的 $v$

判断是否能够重新排序,$n\le 10^5$

Solution

一个显然的贪心是如果在考虑 $k$ 的限制的情况下,对于每个 $a$ 的元素,我们找 $b$ 中第一个大于它的元素,然后实现配对

注意到相同年龄是一段可交换区间,我们拿 $multiset$ 维护这个东西

并不是很好写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cctype>
#include <stack>
#include <queue>
#include <set>
#define gc getchar
#define ll long long
#define maxn 200010
#define pb push_back
using namespace std;

int read() {
int x = 0; char c = gc();
while (!isdigit(c)) c = gc();
while (isdigit(c)) x = x * 10 + c - '0', c = gc();
return x;
}

int n;

struct node {
int v, k;
} A[maxn], B[maxn];

multiset<int> s1[maxn], s2[maxn], S;
multiset<int>::iterator it, It;

int a[maxn], c1, b[maxn], c2;

int c[2 * maxn], cnt;
void init_hash() {
for (int i = 1; i <= n; ++i)
a[i] = A[i].k, c[i + n] = B[i].k;
sort(c + 1, c + 2 * n + 1); cnt = unique(c + 1, c + 2 * n + 1) - c - 1;
for (int i = 1; i <= n; ++i) {
A[i].k = lower_bound(c + 1, c + cnt + 1, A[i].k) - c;
B[i].k = lower_bound(c + 1, c + cnt + 1, B[i].k) - c;
}
}

void work() {
n = read(); c1 = c2 = 0;
for (int i = 1; i <= n; ++i) B[i].k = read();
for (int i = 1; i <= n; ++i) B[i].v = read();
for (int i = 1; i <= n; ++i) A[i].k = read();
for (int i = 1; i <= n; ++i) A[i].v = read();
init_hash();
for (int i = 1; i <= n; ++i) {
if (s1[A[i].k].empty()) a[++c1] = A[i].k;
if (s2[B[i].k].empty()) b[++c2] = B[i].k;
s1[A[i].k].insert(A[i].v);
s2[B[i].k].insert(B[i].v);
} sort(a + 1, a + c1 + 1); sort(b + 1, b + c2 + 1);
int j = 1;
for (int i = 1; i <= c1; ++i) {
int id = a[i];
while (S.size() < s1[id].size()) {
for (auto it : s2[b[j]]) S.insert(it);
++j;
}
for (it = s1[id].begin(); it != s1[id].end(); ++it) {
int v = *it; It = S.upper_bound(v);
if (It == S.end()) {
for (int i = 1; i <= c1; ++i) s1[a[i]].clear();
for (int i = 1; i <= c2; ++i) s2[b[i]].clear();
S.clear(); puts("No");
return ;
}
S.erase(It);
}
} puts("Yes");
for (int i = 1; i <= c1; ++i) s1[a[i]].clear();
for (int i = 1; i <= c2; ++i) s2[b[i]].clear();
S.clear();
}

int main() {
int T; cin >> T;
while (T--) work();
return 0;
}