Increasing Triples
题目链接:ARC 123B
题目大意
给你三个长度为 n 的数组 ai,bi,ci。
你可以把这三个数组里面的数任意换位置(只能一个数组内换)。
然后要你最大化满足条件的下标。
条件是:这一位 i 有 ai<bi<ci。
思路
首先显然是排序。
接着我们考虑进行一个贪心。
c
c
c 数组从大到小看,那肯定是合法的是后面的连续一段嘛,你前面有合法的后面不合法你可以把前面的给后面匹配啊(反正更大一定能)。
然后就匹配,至于找谁匹配肯定是找第一个小于他的,我们可以用 lower_bound 函数解决。(注意 lower_bound 找到的是第一个大于等于的,所以我们要的是它找到 − 1 -1 −1)。
然后显然 b , a b,a b,a 的匹配也是从大到小,那每次确定之后我们就可以把 lower_bound 要找的范围缩小。
那如果 lower_bound 找不到或者已经没有范围了,那就是匹配到这里不能匹配了。输出当前匹配了多少个就好。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n, a[100001], b[100001], c[100001], at, bt;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
sort(a + 1, a + n + 1);
sort(b + 1, b + n + 1);
sort(c + 1, c + n + 1);
at = n; bt = n;
for (int i = n; i >= 1; i--) {//从大到小匹配 c
int now = lower_bound(b + 1, b + bt + 1, c[i]) - b;//找到第一个合适的 b(这里找的是它的下一位)
if (now == 1 || !bt) {//不能匹配后面就都不能了(下面的也一样)
printf("%d", n - i);
return 0;
}
bt = now - 2;//记录能用位置的变化(下面也一样)
now = lower_bound(a + 1, a + at + 1, b[now - 1]) - a;//同样方法找到 a
if (now == 1 || !at) {
printf("%d", n - i);
return 0;
}
at = now - 2;
}
printf("%d", n);//一直都可以
return 0;
}