题目链接:https://vjudge.net/problem/HDU-6635
题意:n个数,原先都被覆盖了,每次显示一个数,求每次的LIS
题解:1 到 N 的排列,最长上升子序列(LIS)长度的期望是多少:https://www.zhihu.com/question/266958886
所以LIS大约是100,我们倒着操作,相当于每次去掉一个数,看一下这个数是不是LIS里的数,如果是的话,那就在找一个LIS,不是的话那就继续进行。找LIS的时候用nlog(n)的求法,每次记录下到每个数时的LIS,然后倒着找一个LIS记录下来即可
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
int p[N], k[N];
int n;
int a[N], len, b[N], vis[N];
int ans[N];
void LIS() {
len = 0;
int pos;
for(int i = 1; i <= n; i++) {
vis[i] = 0;
if(p[i] == 0) continue;
pos = lower_bound(a + 1, a + 1 + len, p[i]) - a;
if(pos > len) {
a[++len] = p[i];
b[i] = len;
} else {
a[pos] = p[i];
b[i] = pos;
}
}
pos = len;
for(int i = n; pos && i >= 1; i--) {
if(!p[i]) continue;
if(b[i] == pos) {
vis[i] = 1;
pos--;
}
}
}
int main() {
int T, pos;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &p[i]);
for(int i = 1; i <= n; i++) scanf("%d", &k[i]);
LIS();
for(int i = n; i >= 1; i--) {
ans[i] = len;
p[k[i]] = 0;
if(vis[k[i]]) {
LIS();
}
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}