其他分享
首页 > 其他分享> > 【YCOJ 1059】最长上升子序列

【YCOJ 1059】最长上升子序列

作者:互联网

1059 -- 最长上升子序列

Description

维护一个序列,使它可以进行下面两种操作:
1.在末尾添加一个数字x
2.将整个序列变成第x次操作后的样子
在每次操作后,输出当前序列的最长上升子序列的长度
序列初始时为空

Input

第一行有一个正整数n,表示操作个数。
接下来n行每行有两个整数op,x。如果op为0,则表示添加x这个数字;如果op为1,则表示回到第x次操作之后。

Output

对于每次操作,输出一个答案,表示当前最长上升子序列的长度。

Sample Input

5
0 2
0 0
1 0
1 0
0 5

Sample Output

1
1
0
0
1

Hint

30%的数据: n≤1000;
另外20%的数据没有第二个的操作
80%的数据: n≤200000;
100%的数据:n≤500000 ,且所有输入的数字都是长整型范围内的非负整数

Source

2014NOIP模拟题

Hide Information »

 题解:我觉得有点难啊啊啊啊DP题,LIS进阶版哦

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
const ll N=500002;
const ll oo=10000000000000000;
ll op[N],f[N],head[N];
ll a[N];
int ans[N];
struct node{
    ll next;
    ll to;
}e[N];
ll cnt,n;
void add(ll u,ll v){
    cnt++; e[cnt].to=v;
    e[cnt].next=head[u]; head[u]=cnt;
}

void dfs(ll  now){
    if(op[now]==1){
        ans[now]=lower_bound(f,f+1+n,oo)-(f+1);
        for(ll i=head[now];i;i=e[i].next)
            dfs(e[i].to);
    } 
    if(op[now]==0){
        ll ps=lower_bound(f,f+1+n,a[now])-f;
        ll tmp=f[ps]; f[ps]=a[now];
        ans[now]=lower_bound(f,f+1+n,oo)-(f+1);
        for(ll i=head[now];i;i=e[i].next)
            dfs(e[i].to);
        f[ps]=tmp;
    }
}

int main(){
    freopen("1059.in","r",stdin);
    freopen("1059.out","w",stdout);
    cin>>n;
    for(ll i=1;i<=n;i++){
        cin>>op[i]>>a[i];
        if(op[i]==1) add(a[i],i);
        else add(i-1,i);
    }
    op[0]=1;
    for(ll i=1;i<=n;i++) f[i]=oo; dfs(0);
    for(ll i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

 

 

标签:head,include,1059,ll,YCOJ,序列,now,op
来源: https://www.cnblogs.com/wuhu-JJJ/p/11784821.html