從最後一個修改往前遍歷,每次如果凍結的是記錄中的最長上升子序列,就重新暴力一遍最長上升子序列並記錄,注意記錄的時候用path,lis只能求出長度,裏面的數字不一定是最長上升子序列,複雜度因爲是隨機生成的序列,所以最長上升子序列長度平均爲sqrt(n),修改的時候正好去掉當今最長上升子序列中的數的概率不高,出題人不卡特殊數據還把時間開了14秒,所以複雜度爲n*sqrt(n)logn
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <time.h>
#include <algorithm>
typedef long long ll;
using namespace std;
const ll mod=998244353;
const int maxn=1e5+100;
int n;
int p[maxn],k[maxn],ans[maxn];
int vis[maxn],path[maxn];
vector<int>lis;
int f()
{
memset(vis,0,sizeof vis);
memset(path,0,sizeof path);
lis.clear();
for(int i=1;i<=n;i++){
if(p[i]==-1)continue;
if(lis.size()==0 || p[i]>lis[lis.size()-1]){
lis.push_back(p[i]);
path[i]=lis.size();
}
else{
int pos=lower_bound(lis.begin(),lis.end(),p[i])-lis.begin();
lis[pos]=p[i];
path[i]=pos+1;
}
}
int tmp=lis.size();
for(int i=n;i>=1;i--){
if(tmp==0)break;
if(path[i]==tmp){
vis[p[i]]=1;
tmp--;
}
}
return lis.size();
}
int main() {
int t;
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]);
ans[n]=f();
for(int i=n-1;i>=1;i--){
int x=p[k[i+1]];
p[k[i+1]]=-1;
if(vis[x]==1)ans[i]=f();
else ans[i]=ans[i+1];
}
for(int i=1;i<=n;i++){
printf("%d",ans[i]);
printf("%c",i==n?'\n':' ');
}
}
return 0;
}