Another LIS
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1244 Accepted Submission(s): 431
Problem Description
There is a sequence firstly empty. We begin to add number from 1 to N to the sequence, and every time we just add a single number to the sequence at a specific position. Now, we want to know length of the LIS (Longest Increasing Subsequence) after every time's add.
Input
An integer T (T <= 10), indicating there are T test cases.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
Output
For the k-th test case, first output "Case #k:" in a separate line, then followed N lines indicating the answer. Output a blank line after every test case.
Sample Input
1
3
0 0 2
Sample Output
Case #1:
1
1
2
Hint
In the sample, we add three numbers to the sequence, and form three sequences.
a. 1
b. 2 1
c. 2 1 3题意:一个空序列,第k次在xk处 插入 k,并输出 序列当前的LIS。
首先 倒序 用线段树来确定每个元素 最终的位置。然后 求n次LIS,当然要用线段树维护了,,或者二分等等也可以。 nlogn
1 #include <cstdio> 2 #include <string> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 1e5+10; 8 int seg[maxn<<2],a[maxn]; // seg表示该区间 位置剩余量 9 void build (int l,int r,int pos) 10 { 11 if (l == r) 12 { 13 seg[pos] = 1; 14 return; 15 } 16 int mid = (l + r) >> 1; 17 build(l,mid,pos<<1); 18 build(mid+1,r,pos<<1|1); 19 seg[pos] = seg[pos<<1] + seg[pos<<1|1]; 20 } 21 int ans[maxn]; //ans[i]表示 元素i的位置为ans[i] 22 void Insert(int l,int r,int pos,int x,int k) 23 { 24 if (l == r) 25 { 26 ans[k] = l; 27 seg[pos] = 0; 28 return ; 29 } 30 int mid = (l + r) >> 1; 31 if (seg[pos<<1] >= x) //左孩子的区间 位置剩余量大于x时,递归进入左孩子,否则右孩子同时 x-seg[pos<<1] 32 Insert(l,mid,pos<<1,x,k); 33 else 34 Insert(mid+1,r,pos<<1|1,x - seg[pos<<1],k); 35 seg[pos] = seg[pos<<1] + seg[pos<<1|1]; 36 } 37 void update(int l,int r,int pos,int x,int v) 38 { 39 if (l == r) 40 { 41 seg[pos] = v; 42 return; 43 } 44 int mid = (l + r) >> 1; 45 if (x <= mid) 46 update(l,mid,pos<<1,x,v); 47 else 48 update(mid+1,r,pos<<1|1,x,v); 49 seg[pos] = max(seg[pos<<1],seg[pos<<1|1]); 50 } 51 int query(int l,int r,int pos,int ua,int ub) 52 { 53 if (ua <= l && ub >= r) 54 { 55 return seg[pos]; 56 } 57 int mid = (l + r) >> 1; 58 int t1 = 0,t2 = 0; 59 if (ua <= mid) 60 t1 = query(l,mid,pos<<1,ua,ub); 61 if (ub > mid) 62 t2 = query(mid+1,r,pos<<1|1,ua,ub); 63 return max(t1,t2); 64 } 65 66 int main(void) 67 { 68 #ifndef ONLINE_JUDGE 69 freopen("in.txt","r",stdin); 70 #endif 71 int t,cas = 1; 72 scanf ("%d",&t); 73 while (t--) 74 { 75 int n; 76 scanf ("%d",&n); 77 for (int i = 1; i <= n; i++) 78 scanf ("%d",a+i); 79 build (1,n,1); 80 for (int i = n; i >= 1; i--) 81 Insert(1,n,1,a[i] + 1,i); //倒序 确定每个元素 最终的位置保存在ans里 82 memset(seg,0,sizeof(seg)); 83 printf("Case #%d: ",cas++); 84 for (int i = 1; i <= n; i++) 85 { 86 int t1 = query(1,n,1,1,n); 87 int t2 = query(1,n,1,1,ans[i]); 88 update(1,n,1,ans[i],t2+1); 89 if (t2 < t1) //输出当前区间的LIS 90 printf("%d ",t1); 91 else 92 printf("%d ",1+t2); 93 } 94 printf(" "); 95 } 96 return 0; 97 }