题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6635
题意
给出一串数,一开始没有一个数可用。每次选一个数变成可用,问此时的最长上升子序列是多少。
题解
结论:随机数据的LIS长度期望是
n
\sqrt{n}
n
所以反过来做,时间复杂度就是
O
(
n
n
l
o
g
(
n
)
)
O(n\sqrt{n}log(n))
O(nnlog(n))
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=5e4+7;
int t,n;
int p[N],k[N];
int ans[N],tp=0;
bool in[N];
int pr[N];
int dp[N];
void get(){
tp=0;
for(int i=1;i<=n;i++){
if(!p[i]) continue;
int pos=lower_bound(ans+1,ans+1+tp,p[i])-ans;
if(pos>tp) ans[++tp]=p[i];
else ans[pos]=p[i];
dp[i]=pos;
}
int now=tp,lst=n+1;
for(int i=n;i>=1;i--){
if(dp[i]==now&&p[i]<=lst&&p[i]){
lst=p[i];
in[i]=true;
now--;
}
else in[i]=false;
}
}
int main(){
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]);
}
get();
for(int i=n;i>=1;i--){
pr[i]=tp;
p[k[i]]=0;
if(in[k[i]]) get();
}
for(int i=1;i<=n;i++){
printf("%d%c",pr[i],i==n?'\n':' ');
}
}
}