bzoj 3173 [Tjoi2013]最长上升子序列 (treap模拟+lis)
[Tjoi2013]最长上升子序列
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2213 Solved: 1119
[Submit][Status][Discuss]
Description
给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?
Input
第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)
Output
N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。
Sample Input
3
0 0 2
0 0 2
Sample Output
1
1
2
1
2
HINT
100%的数据 n<=100000
Source
题解
这道题目因为是顺序插入,求的是最长上升子序列,所以不改变当前位置的
最长上升序列长度。
放一个大的数在前面不影响,在中间,不影响,在后面,当当前位置为止的话也还是不影响的。
所以只需要模拟出最后序列即可,怎么模拟,是关键。
我是用平衡树维护的。
点的编号即为当前插入点。
最后求一次LIS即可。
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 7 #define ls tr[p].l 8 #define rs tr[p].r 9 #define N 100007 10 #define inf 1000000007 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 16 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 20 int n,m,sz,rt,bh,top,now; 21 char flag[3]; 22 int f[N],v[N],ans[N]; 23 struct Node 24 { 25 int l,r,val,siz,rnd; 26 }tr[N]; 27 28 inline int rand() 29 { 30 static int seed=2333; 31 return seed=(int)((((seed^998244353)+19260817ll)*19890604ll)%1000000007); 32 } 33 34 inline void update(int p) 35 { 36 tr[p].siz=tr[ls].siz+tr[rs].siz+1; 37 } 38 void lturn(int &p) 39 { 40 int t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p; 41 tr[t].siz=tr[p].siz;update(p);p=t; 42 } 43 void rturn(int &p) 44 { 45 int t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p; 46 tr[t].siz=tr[p].siz;update(p);p=t; 47 } 48 void ins(int &p,int x) 49 { 50 if (p==0) 51 { 52 p=++sz; 53 tr[p].siz=1,tr[p].rnd=rand(); 54 return; 55 } 56 tr[p].siz++; 57 if (tr[ls].siz<x) 58 { 59 ins(rs,x-tr[ls].siz-1); 60 if (tr[rs].rnd<tr[p].rnd) lturn(p); 61 } 62 else 63 { 64 ins(ls,x); 65 if (tr[ls].rnd<tr[p].rnd) rturn(p); 66 } 67 } 68 void dfs(int p) 69 { 70 if (!p) return; 71 dfs(ls); 72 v[++now]=p; 73 dfs(rs); 74 } 75 void solve() 76 { 77 memset(f,127,sizeof(f)),f[0]=-inf; 78 for (int i=1;i<=n;i++) 79 { 80 int t=upper_bound(f,f+top+1,v[i])-f; 81 if (f[t-1]<=v[i]) 82 { 83 f[t]=min(f[t],v[i]); 84 ans[v[i]]=t; 85 top=max(t,top); 86 } 87 } 88 } 89 int main() 90 { 91 n=read(); 92 for (int i=1;i<=n;i++) 93 { 94 int x=read();now=i; 95 ins(rt,x); 96 } 97 now=0,dfs(rt); 98 solve(); 99 for (int i=1;i<=n;i++) 100 { 101 ans[i]=max(ans[i-1],ans[i]); 102 printf("%d\n",ans[i]); 103 } 104 }