https://www.lydsy.com/JudgeOnline/problem.php?id=3173php
插入的數是以遞增的順序插入的ios
這說明若是倒過來考慮,那麼從最後一個插入的開始刪除,不會對以某個數結尾的最長上升子序列產生影響git
因此 先原序列求出來,輸出便可數組
還原原序列的方法:spa
能夠用平衡樹,dfs序就是原序列code
嫌麻煩,不想寫,因此 樹狀數組blog
假設最後一個數是n,插入位置是y,get
倒數第二個數是n-1,插入位置是xit
那麼y就是n的最終位置io
若是y在x後面,那麼x就是n-1的最終位置
若是y在x前面,那麼x+1就是n-1的最終位置
因此 若是倒序插入每一個數,
若數m的插入位置爲p,
數m的最終位置就是當前序列 的 第p個空位
這能夠二分+樹狀數組肯定 數m的位置
注意求LIS時,求出的f[i] 時 以i結尾的LIS
要求回答 序列的LIS,因此要跟f[i-1]取大
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 #define lowbit(x) x&-x int n; int p[N]; int c[N]; int a[N]; int dp[N],m; int f[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void add(int pos,int x) { while(pos<=n) { c[pos]+=x; pos+=lowbit(pos); } } int query(int x) { int sum=0; while(x) { sum+=c[x]; x-=lowbit(x); } return sum; } int find(int x) { int l=1,r=n,mid,tmp; while(l<=r) { mid=l+r>>1; if(mid-query(mid)>=x) tmp=mid,r=mid-1; else l=mid+1; } return tmp; } void init() { read(n); for(int i=1;i<=n;++i) read(p[i]); int pos; for(int i=n;i;--i) { pos=find(p[i]+1); a[pos]=i; add(pos,1); } } void pre_LIS() { dp[m=1]=a[1]; f[a[1]]=1; int pos; for(int i=2;i<=n;++i) { if(a[i]>dp[m]) { dp[++m]=a[i]; f[a[i]]=m; } else { pos=lower_bound(dp+1,dp+m+1,a[i])-dp; if(a[i]<dp[pos]) dp[pos]=a[i]; f[a[i]]=pos; } } } void solve() { int now=0; for(int i=1;i<=n;++i) { now=max(now,f[i]); printf("%d\n",now); } } int main() { init(); pre_LIS(); solve(); }