这题用fhqtreap可以在线。

  fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影响。

  然后就可以直接fhqtreap模拟啦

  忘记所有答案取max WA了半天T T

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define lt tree[x].ls
#define rt tree[x].rs
using namespace std;
const int maxn=500010, seed=233333, inf=1e9+1;
struct treap{int sum, mx, rnd, size, ls, rs;}tree[maxn];
int n, x, tott, root, ans;
void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
    while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
    k*=f;
}
inline void build(int &x)
{
    tree[x=++tott].rnd=rand()<<15|rand();
    tree[x].sum=tree[x].mx=tree[x].size=1;
}
inline int max(int a, int b){return a>b?a:b;}
inline void up(int x)
{
    if(!x) return;
    tree[x].size=tree[lt].size+tree[rt].size+1;
    tree[x].mx=max(tree[x].sum, max(tree[lt].mx, tree[rt].mx));
}
void split(int x, int &l, int &r, int k)
{
    if(!k) l=0, r=x;
    else if(k==tree[x].size) l=x, r=0;
    else if(k<=tree[lt].size) r=x, split(lt, l, lt, k), up(x);
    else l=x, split(rt, rt, r, k-tree[lt].size-1), up(x);
}
void merge(int &x, int l, int r)
{
    if(!l || !r) x=l+r;
    else if(tree[l].rnd<tree[r].rnd) x=l, merge(rt, rt, r), up(x);
    else x=r, merge(lt, l, lt), up(x);
}
inline int solve(int pos)
{
    int x, y, tmp;
    build(tmp); split(root, x, y, pos); 
    tree[tmp].sum=tree[tmp].mx=max(0, tree[x].mx)+1; 
    merge(x, x, tmp); merge(root, x, y);
    return ans=max(ans, tree[tmp].sum);
}
int main()
{
    srand(seed); read(n); tree[0].mx=-inf; tree[0].rnd=inf;
    for(int i=1;i<=n;i++) read(x), printf("%d\n", solve(x)); 
}
View Code

相关文章: