HDU-3564 Another LIS

老子叫甜甜 提交于 2020-02-13 17:16:59

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.
 

 

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
zhouzeyong   |   We have carefully selected several similar problems for you:  3572 2389 3584 3293 1166 
 
一道插空线段树 + 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;
    }
}

 

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!