zoukankan      html  css  js  c++  java
  • [51Nod 1218] 最长递增子序列 V2 (LIS)

    传送门

    Description

    数组A包含N个整数。设S为A的子序列且S中的元素是递增的,则S为A的递增子序列。如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS)。A的LIS可能有很多个。例如A为:1 3 2 0 4,1 3 4,1 2 4均为A的LIS。其中元素1和4一定会出现在LIS当中,元素2和3可能会出现在LIS当中,元素0一定不会出现在LIS当中。给出数组A,输出哪些数可能出现在LIS中,哪些数一定出现在LIS中。输出数字对应的下标,下标编号从1开始,编号为1 - N。例如:1 3 2 0 4,可能出现的元素为3和2,对应的下标为2和3。一定出现的元素为1和4,对应下标为1和5.

    Input

    第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
    第2 - N + 1行:每行1个数A[i],表示数组的元素(0 <= A[i] <= 10^9)

    Output

    第1行:可能出现在LIS中的数的下标,中间用空格分隔。(输出的下标按照递增排序)
    第2行:一定会出现在LIS中的数的下标,中间用空格分隔。(输出的下标按照递增排序)

    Sample Input

    5
    1
    3
    2
    0
    4

    Sample Output

    A:2 3
    B:1 5

    Solution

    正的跑最长上升子序列,反的跑最长下降子序列
    如果正反的dp值相加等于len+1(自己加了两次)说明可能在LIS中
    若dp值独一无二且可能出现即为一定出现

    Code

    //By Menteur_Hxy
    #include <cmath>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define R(i,a,b) for(register int i=(b);i>=(a);i--)
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
    using namespace std;
    
    char buf[1<<21],*p1,*p2;
    inline int read() {
    	int x=0,f=1; char c=getchar();
    	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    	return x*f;
    }
    
    const int N=50010;
    int n,len;
    bool vis1[N],vis2[N];
    int a[N],s[N],f[N],g[N];
    vector<int> V[N];
    
    int main() {
    	n=read();
    	F(i,1,n) a[i]=read();
    	F(i,1,n) {
    		if(s[len]<a[i]) s[++len]=a[i],f[i]=len;
    		else {
    			int tmp=lower_bound(s+1,s+1+len,a[i])-s;
    			s[tmp]=a[i];f[i]=tmp;
    		}
    	}
    	len=0;
    	R(i,1,n) {
    		if(s[len]<-a[i]||!len) s[++len]=-a[i],g[i]=len;//无脑取负qwq
    		else {
    			int tmp=lower_bound(s+1,s+1+len,-a[i])-s;
    			s[tmp]=-a[i];g[i]=tmp;
    		}
    	}
    	F(i,1,n) {
    		if(f[i]+g[i]==len+1) vis1[i]=1;
    		if(vis1[i]) V[f[i]].push_back(i);
    	}
    	F(i,1,n) {
    		int siz=V[i].size();
    		if(siz==1) vis2[V[i][0]]=1;
    	}
    	// F(i,1,n) cout<<f[i]<<" ";cout<<endl;
    	// F(i,1,n) cout<<g[i]<<" ";cout<<endl;
    	putchar('A');putchar(':'); F(i,1,n) if(vis1[i]&&!vis2[i]) printf("%d ",i);
    	putchar('
    ');
    	putchar('B');putchar(':'); F(i,1,n) if(vis2[i]) printf("%d ",i);
    	return 0;
    }
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    【JavaScript】Object 实例属性
    【JavaScript】Object 构造函数和属性
    【JavaScript】Object 静态方法(三)
    PTA 乙级 1051 复数乘法 (15分) Python
    PTA 乙级 1050 螺旋矩阵 (25分) C++
    PTA 乙级 1049 数列的片段和 (20分) C/C++ (更新OJ导致测试点2无法通过,已解决)
    对象的深拷贝和浅拷贝和拷贝方法
    linux(腾讯云服务器)上安装mysql数据库
    SQLyog远程连接mysql数据库
    linux中搭建tomcat环境
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9643281.html
Copyright © 2011-2022 走看看