Nonsense Time
时间限制: 10 Sec 内存限制: 128 MB题目描述
For each i, find the longest increasing subsequence among available elements after the first i stages.
输入
In each test case, there is one integer n(1≤n≤50000) in the first line, denoting the size of permutation.
In the second line, there are n distinct integers p1,p2,...,pn(1≤pi≤n), denoting the permutation.
In the third line, there are n distinct integers k1,k2,...,kn(1≤ki≤n), describing each stage.
It is guaranteed that p1,p2,...,pn and k1,k2,...,kn are generated randomly.
输出
样例输入
1
5
2 5 3 1 4
1 4 5 3 2
样例输出
1 1 2 3 3
题意:有一个数列, 一开始这些数都不可用,接下来每次会让一个位置上的数变得可用,求每次操作后可用数的LIS。
思路:前置知识:长度为N的全排列的LIS的期望为sqrt(N),于是可以倒着让这些数变得不可用,如果它不是LIS上的数就对答案没影响,否则就暴力重新nlogn跑LIS。因为LIS的期望长度为sqrt(N),所以删除某一个数,该数是LIS上的数的概率是1/sqrt(N),也就是说期望会有sqrt(N)个数在LIS上,于是我们最多跑sqrt(N)遍暴力,期望复杂度:O(n*sqrt(n)*log(n))。


#include<bits/stdc++.h> using namespace std; const int N = 50050; int arr[N],b[N]={0},len; int k[N],vis[N]={0}; int pre[N]; int if_lis[N],id[N];int Serach(int num,int low,int high) {int mid;while (low<=high) {mid=(low+high)>>1;if (num>=b[mid]) low=mid+1;else high=mid-1;}return low; }void DP(int n) {len=0;b[len]=-1;id[len]=-1;for(int i=1;i<=n;i++){if(!vis[i])continue;if(arr[i]>=b[len]){len++;b[len]=arr[i];id[len]=i;pre[i]=id[len-1];}else{int pos=Serach(arr[i],1,len);b[pos]=arr[i];pre[i]=id[pos-1];id[pos]=i;}}memset(if_lis,0,sizeof(if_lis));int now=id[len];while(now!=-1){if_lis[now]=1;now=pre[now];} }int ans[N]; int main() {int t;scanf("%d",&t);while(t--){int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&arr[i]);for(int i=1;i<=n;i++)scanf("%d",&k[i]);for(int i=1;i<=n;i++)vis[i]=1;DP(n);ans[n]=len;for(int i=n-1;i>=1;i--){vis[k[i+1]]=0;if(!if_lis[k[i+1]]){ans[i]=ans[i+1];continue;}DP(n);ans[i]=len;}for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n ? '\n' : ' ');}return 0; }