Another LIS
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2127 Accepted Submission(s): 771
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
Author
standy
Source
Recommend
一道插空线段树 + lis
求1~n的位置
从1~n枚举
因为1~n递增
所以只要找
他们的位置递增的lis就可以了
要用到nlogn lis
#include<bits/stdc++.h>
const int maxn = 1e5 + 5;
using namespace std;
int leaf[maxn];
int pos[maxn];
int val[maxn];
int ans[maxn];
int b[maxn];
int n;
int t;
struct node{
int l, r;
int w;
}tree[maxn * 4];
void build(int i, int l, int r){
tree[i].l = l;
tree[i].r = r;
tree[i].w = 0;
if(l == r){
tree[i].w = 1;
leaf[l] = i;
return ;
}
int mid = (l + r) >> 1;
build(i << 1, l, mid);
build((i << 1) + 1, mid + 1, r);
tree[i].w = tree[i << 1].w + tree[i << 1 | 1].w;
}
void update(int x){
if(x == 1)
return ;
int fa = x >> 1;
int ls = tree[fa << 1].w;
int rs = tree[(fa << 1) + 1].w;
tree[fa].w = ls + rs;
update(fa);
}
int query(int p, int i, int l, int r){
if(tree[i].w < p)
return -1;
if(tree[i].l == tree[i].r){
return tree[i].l;
}
int mid = (tree[i].l + tree[i].r) >> 1;
int ss = query(p, i << 1, l, mid);
if(ss == -1){
int sss = query(p - tree[i << 1].w, i << 1 | 1, mid + 1, r);
return sss;
}
return ss;
}
void solve(){
int tot = 0;
memset(b, 0, sizeof(b));
b[++tot] = ans[1];
cout << 1 << endl;
for(int i = 2; i <= n; i++){
if(ans[i] > b[tot]){
b[++tot] = a[i];
}
else{
int p = lower_bound(b + 1, b + tot + 1, ans[i]) - b;
b[p] = ans[i];
}
cout << tot << endl;
}
}
int main(){
ios::sync_with_stdio(0);
cin >> t;
int o = t;
while(t--){
cin >> n;
cout << "Case #" << o - t << ":" << endl;
build(1, 1, n);
for(int i = 1; i <= n; i++){
cin >> pos[i];
val[i] = i;
pos[i]++;
}
for(int i = n; i >= 1; i--){
int p = query(pos[i], 1, 1, n);
ans[i] = p;
tree[leaf[p]].w -= 1;
update(leaf[p]);
}
solve();
cout << endl;
}
}
来源:CSDN
作者:箱@子
链接:https://blog.csdn.net/qq_33914105/article/details/104297479