zoukankan      html  css  js  c++  java
  • [DP][二分]JZOJ 3467 最长上升子序列

    Description

    维护一个序列,使它可以进行下面两种操作:

    1.在末尾添加一个数字x

    2.将整个序列变成第x次操作后的样子

    在每次操作后,输出当前序列的最长上升子序列的长度

    序列初始时为空
     

    Input

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

    Output

    对于每次操作,在输出文件lis.out中输出一个答案,表示当前最长上升子序列的长度
     

    Sample Input

    5
    0 2
    0 0
    1 0
    1 0
    0 5

    Sample Output

    1
    1
    0
    0
    1
    【样例说明】
    第一次操作后,序列为 2
    第二次操作后,序列为2 0
    第三次操作后,序列为(空)
    第四次操作后,序列为(空)
    第五次操作后,序列为 5
     

    Data Constraint

    30%的数据  n<=1000

    另外20%的数据没有第二个操作

    80%的数据 n<=200000

    100%的数据 n<=500000且所有输入的数字都是长整型范围内的非负整数

    分析

    我们可以容易发现这个题的数据输入呈一个树形,但是我们无法每次都对一条链求最长上升子序列。

    然后想到DFS可以重置一些东西,记录一些相关的变化量再退回即可。

    (然后传统DFS居然爆栈了?)手写一个while版的DFS= =

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=500001;
    struct Edge {
        int u,v,nx;
    }g[N];
    struct D {
        int j,k,u,v;
        bool b;
    }stk[N];
    int top;
    int cnt,list[N];
    int f[N],d[N],num[N],w[N];
    int pcnt,mlen;
    int n;
    
    void Add(int u,int v) {
        g[++cnt].u=u;g[cnt].v=v;g[cnt].nx=list[u];list[u]=cnt;
    }
    
    void Dfs(int u) {
        stk[top].u=u;
        while (1) {
            while (!list[stk[top].u]&&top>0) 
            {
                top--;
                if (stk[top].b) d[mlen--]=0;
                else if (stk[top].j>0) d[stk[top].j]=stk[top].k;
            };
            if (!list[stk[top].u]) break;
            int i=list[stk[top].u];
            list[stk[top].u]=g[i].nx;
            stk[top].v=g[i].v;
            stk[top].b=0;
            if (d[mlen]<w[stk[top].v]) {
                d[++mlen]=w[stk[top].v];
                stk[top].b=1;
            }
            else {
                stk[top].j=lower_bound(d,d+mlen+1,w[stk[top].v])-d;
                if (stk[top].j>0) stk[top].k=d[stk[top].j],d[stk[top].j]=w[stk[top].v];
            }
            f[stk[top].v]=mlen;
            top++;
            stk[top].u=stk[top-1].v;
        }
    }
    
    void Init() {
        scanf("%d",&n);
        num[0]=0;
        for (int i=1;i<=n;i++) {
            int order,p;
            scanf("%d%d",&order,&p);
            if (order)
            num[i]=num[p];
            else {
                num[i]=++pcnt;
                Add(num[i-1],num[i]);
                w[pcnt]=p;
            }
        }
        d[0]=-2147483647;mlen=0;
    }
    
    void Print() {
        for (int i=1;i<=n;i++)
        printf("%d\n",f[num[i]]);
    }
    
    int main() {
        freopen("lis.in","r",stdin);
        freopen("lis.out","w",stdout);
        Init();
        Dfs(0);
        Print();
        fclose(stdin);fclose(stdout);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    关于今后的进展
    很久没来了
    达到极限了
    寒假进度4Scala环境配置
    寒假进度3Jupyter运行PyTorch
    寒假进度2Pycharm运行PyTorch
    寒假进度7Python与Jupyter使用对比
    寒假进度6音频多人声分离赛题分析
    《Google的软件测试之道》(5)
    《Google的软件测试之道》(6)
  • 原文地址:https://www.cnblogs.com/mastervan/p/9426889.html
Copyright © 2011-2022 走看看