题目

luogu

思路

每次都是插入比之前所有数字大的数,所以之前的答案就不会改变
用fhq-treap求出原序列,然后用树状数组依次算出每个值得lis(显然g[i]=g[i-j]+1)
然后答案就是前i个得最大值(答案一定是不降的)
这里具体讲一下fhq-treap
如果你还是维护val的话,显然不对
如果要在x的位置插入y
那么我们就要把前x个和后size[rt]-x个分开
这里的关键字就成了size了(显然)
然后你就按照size进行分裂
注意递归的关键字的改变

split(ch[now][1],k-size[ch[now][0]]-1,ch[x][1],y);

错误&&傻叉

1.pushup(rt)
2.一脸茫然只会模板

代码

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=1e5+7;
const int inf=0x3f3f3f3f; 
int n,rt,a[maxn],a_size;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f; 
}
struct node {
    int ch[maxn][2],val[maxn],pri[maxn],size[maxn],cnt;
    int make_edge(int a) {val[++cnt]=a;size[cnt]=1;pri[cnt]=rand();return cnt;}
    void pushup(int x) {size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
    int merge(int x,int y) {
        if(!x||!y) return x+y;
        if(pri[x]<pri[y]) { 
            ch[x][1]=merge(ch[x][1],y); 
            pushup(x);return x;
        } else { 
            ch[y][0]=merge(x,ch[y][0]);
            pushup(y);return y;
        }
    }
    void split(int now,int k,int &x,int &y) {
        if(!now) x=y=0;
        else {
            if(size[ch[now][0]]+1<=k) x=now,split(ch[now][1],k-size[ch[now][0]]-1,ch[x][1],y);
            else y=now,split(ch[now][0],k,x,ch[y][0]);
            pushup(now);
        }
    }
    void insert(int a,int i) {
        int x,y;
        split(rt,a,x,y);
        rt=merge(merge(x,make_edge(i)),y);
    }
    void dfs(int now) {
        if(!now) return;
        dfs(ch[now][0]);
        a[++a_size]=val[now];
        dfs(ch[now][1]);
    }
}dsr;
struct BIT{
    int ma[maxn];
    int lowbit(int x) {
        return x&(-x);  
    }
    void add(int id,int x) {
        for(int i=id;i<=n;i+=lowbit(i))
            ma[i]=max(ma[i],x); 
    }
    int query(int x) {
        int ans=0;
        for(int i=x;i>=1;i-=lowbit(i))
            ans=max(ma[i],ans);
        return ans; 
    }
}tree;
int ans[maxn];
int main() {
    srand(time(NULL));
    n=read();
    FOR(i,1,n) {
        int x=read();
        dsr.insert(x,i);
    }
    dsr.dfs(rt);
    FOR(i,1,n) {
        ans[a[i]]=tree.query(a[i]-1)+1;
        tree.add(a[i],ans[a[i]]);
    }
    FOR(i,1,n) ans[i]=max(ans[i],ans[i-1]),cout<<ans[i]<<"\n";
    return 0;
}