최장 상승 하위 시퀀스 dp Treap

5908 단어 dpLIStreapbzoj
bzoj3173 [Tjoi 2013] 최장 상승자 서열 제목: 이에 따라 1-n을 삽입하여 매번 삽입된 LIS 분석을 구한다. 각 수는 승차순에 따라 삽입된 것이기 때문에 매번 한 수를 추가하면 이전의 답안에 영향을 주지 않는다. 그러면 우리는 마지막 서열을 구할 수 있다. 그러면 우리는 각 수를 끝으로 하는 LIS를 구할 수 있다. 그러면 답은 ans[i]=max([ansi],ans[i-1])이다.LIS 현학의 멘붕...이해는 잘 이해한다...멘붕을 실현한다...d[len]: 길이가 렌인 LIS의 끝 최소치 d[i]=max(j)+1 그 중에서 d[j] = 키의 첫 번째 요소를 가리키는 교체기를 되돌려줍니다.iterator upper_bound (const key type & key): 키 값 > 키의 첫 번째 요소를 가리키는 교체기를 되돌려줍니다.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define N 100005
#define mp make_pair
#define pa pair<int,int>
#define inf 1<<30
using namespace std;
struct Node{int ls,rs,v,key,sz;}t[N];
void upd(int k){t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;}
int num,root,n,x,cnt,a[N],d[N],ans[N],da[N];
int merge(int a,int b){
    if(a==0||b==0) return a+b;
    if(t[a].key<t[b].key){t[a].rs=merge(t[a].rs,b);upd(a);return a;}
    else {t[b].ls=merge(a,t[b].ls);upd(b);return b;}
}
pa split(int k,int x){
    if(x==0) return mp(0,k);
    int ls=t[k].ls,rs=t[k].rs;pa tmp;
    if(t[ls].sz==x) {t[k].ls=0;upd(k);return mp(ls,k);}
    if(t[ls].sz==x-1) {t[k].rs=0;upd(k);return mp(k,rs);}
    if(t[ls].sz>x) {tmp=split(ls,x);t[k].ls=tmp.second;upd(k);return mp(tmp.first,k);}
    if(t[ls].sz<x-1) {tmp=split(rs,x-t[ls].sz-1);t[k].rs=tmp.first;upd(k);return mp(k,tmp.second);}
}
void ins(int x,int v){
    int k=x-1;
    t[++num].ls=0;t[num].rs=0;t[num].sz=1;
    t[num].v=v;t[num].key=rand();
    pa tmp=split(root,k);
    root=merge(tmp.first,num);
    root=merge(root,tmp.second);
}
void dfs(int i){
    if(!i) return;
    dfs(t[i].ls);
    a[++cnt]=i;
    dfs(t[i].rs);
}
void getans(){
    memset(d,127,sizeof(d));
    d[0]=-inf;d[1]=a[1];ans[a[1]]=1;
    int len=1;
    for(int i=2;i<=n;i++){
        int pos=upper_bound(d,d+len,a[i])-d;
        if(a[i]>d[len]) d[++len]=a[i],ans[a[i]]=len;
        else d[pos]=min(d[pos],a[i]),ans[a[i]]=pos;
    }
    for(int i=1;i<=n;i++) ans[i]=max(ans[i],ans[i-1]);
    for(int i=1;i<=n;i++) printf("%d
"
,ans[i]); } int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&x),ins(x+1,i); dfs(root); getans(); }

좋은 웹페이지 즐겨찾기