zoukankan      html  css  js  c++  java
  • P2215 [HAOI2007]上升序列

    题目描述

    对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1<x2<…<xm) 且(ax1<ax2<…<axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。

    任务 给出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.

    输入输出格式

    输入格式:

    第一行一个N,表示序列一共有N个元素

    第二行N个数,为a1,a2,…,an

    第三行一个M,表示询问次数。下面接M行每行一个数L,表示要询问长度为L的上升序列。

    输出格式:

    对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.

    输入输出样例

    输入样例#1: 
    6
    3 4 1 2 3 6
    3
    6
    4
    5
    
    输出样例#1: 
    Impossible
    1 2 3 6
    Impossible
    

    说明

    数据范围

    N<=10000

    M<=1000

    Solution:

      本题简直有毒!数据包也有毒!~调了我好久啊!~

      其实本题一个很简单的思路就是:

      先暴力$O(n^2)$处理出以每一位为起点最长上升子序列的长度,那么直接该成倒序即可,这样$f[i]$就表示以$i$为起点最长上升子序列长度。

      然后每次询问长度为$x$的上升子序列是否存在:当$x > L_{max}$时,则直接输出$Impossible$; 否则,由于题目要求下标字典序最小,那么贪心从前往后扫能输出就输出,即记录前一个的值,当前值大于上一个值时就输出。

    代码:

    #include<bits/stdc++.h>
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define il inline
    using namespace std;
    const int N=10005;
    int n,m,x,a[N],f[N],mx[N];
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    int main(){
        n=gi();
        For(i,1,n) a[i]=gi(),f[i]=1;
        mx[n]=1;
        Bor(i,1,n-1) {
            For(j,i+1,n)
                if(f[i]>mx[i+1]+1)break;
                else if(a[i]<a[j]&&f[i]<f[j]+1)f[i]=f[j]+1;
            mx[i]=Max(mx[i+1],f[i]);
        }
        m=gi();
        while(m--){
            x=gi();
            if(x<=mx[1]){
                int p=-520;
                For(i,1,n){
                    if(!x)break;
                    if(f[i]>=x&&a[i]>p)printf("%d ",a[i]),x--,p=a[i];
                }
                printf("
    ");
            }
            else printf("Impossible
    ");
        }
        return 0;
    }
  • 相关阅读:
    POJ1182 食物链---(经典种类并查集)
    HDU1025---(LIS 最长上升子序列 的应用)
    HDU5748---(记录每个元素的 最长上升子序列 nlogn)
    c++ 批量初始化数组 fill和fill_n函数的应用
    JNI 方法注册与签名+BufferedReader使用readLine问题
    正确在遍历中删除List元素
    Head First Java设计模式思维导图总结
    关于一些基础的Java问题的解答(七)
    关于一些基础的Java问题的解答(六)
    关于一些基础的Java问题的解答(四)
  • 原文地址:https://www.cnblogs.com/five20/p/9050767.html
Copyright © 2011-2022 走看看