BZOJ 3173: [Tjoi2013]最长上升子序列

来源:互联网 发布:隐形眼镜 知乎 编辑:程序博客网 时间:2024/06/06 00:27

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

Sample Output

1

1

2

HINT

100%的数据 n<=100000

分析

用treap维护序列后直接求lis

代码

#include <bits/stdc++.h>#define N 100005#define INF 0x7fffffffstruct{    int l,r;    int size;    int rand;    int cover;}t[N];int root, size;void pushUp(int k){    t[k].size = t[t[k].l].size + t[t[k].r].size + 1;}void rttr(int &k){    int tmp = t[k].l;    t[k].l = t[tmp].r;    t[tmp].r = k;    pushUp(k);    pushUp(tmp);    k = tmp;}void rttl(int &k){    int tmp = t[k].r;    t[k].r = t[tmp].l;    t[tmp].l = k;    pushUp(k);    pushUp(tmp);    k = tmp;}void insert(int &x,int rank){    if (!x)    {        x = ++size;        t[x].size = 1;        t[x].rand = rand();        return;    }    t[x].size++;    if (t[t[x].l].size < rank)    {        insert(t[x].r,rank - t[t[x].l].size - 1);        if (t[t[x].r].rand <t[x].rand)            rttl(x);    }    else    {        insert(t[x].l,rank);        if (t[t[x].l].rand < t[x].rand)            rttr(x);    }}int tot;int num[N];void dfs(int x){    if (!x)        return;    dfs(t[x].l);    num[++tot] = x;    dfs(t[x].r);}int pos[N];int ans[N];int mx;int n;void slove(){    memset(pos,127,sizeof(pos));    pos[0] = -INF;    for (int i = 1; i <= n; i++)    {        int tmp = std::upper_bound(pos,pos + mx + 1,num[i]) - pos;        if (pos[tmp - 1] <= num[i])        {            pos[tmp] = std::min(pos[tmp],num[i]);            ans[num[i]] = tmp;            mx = std::max(tmp,mx);        }    }}int main(){    scanf("%d",&n);    for (int i = 1; i <= n; i++)    {        int x;        scanf("%d",&x);        insert(root,x);    }    dfs(root);    slove();    for (int i = 1; i <= n; i++)    {        ans[i] = std::max(ans[i - 1], ans[i]);        printf("%d\n",ans[i]);    }}
0 0
原创粉丝点击