486E - LIS of Sequence(LIS)

题意:给一个长度为n的序列,问每个数关于序列的LIS(longest increasing sequence)是什么角色。这里分了三种:

1、此数没有出现在任意一条LIS中

2、此数出现在至少一条但是不是全部的LIS中

3、此数出现在所有的LIS中

解法:nlgn的LIS算法可以求出以每个i位置结束的LIS长度up[i]。出现在LIS的数其实就是一个dag,找出那些某层唯一数值的数就行。LIS算法后,从后向前扫,维护所以长度的最大值,这中间可以判断某长度有几个值,如果某些长度有多个位置则他们都属于2,如果某长度只有一个位置则属于3,其余都是非LIS元素。在判断多个的时候,某个数num[i]可以松弛他的长度位置,条件要保证他比此时help[up[i+1]]的数小,因为这样才能保证他在LIS中(LIS最后一个元素是特判的)。

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#define inf 10000000

using namespace std;
const int Max=100010;
int num[Max];
int up[Max];
int down[Max];
int D[Max];
void getLIS(int num[],int n)
{
    int last=0;
    for(int i=0; i<n; i++)
    {
        up[i]=lower_bound(D,D+last,num[i])-D+1;
        if(up[i]>last) D[last = up[i]]=num[i];
        D[up[i]-1]=num[i];
    }
}
int help[Max];
int ne[Max];
int ans[Max];
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            scanf("%d",num+i);
        getLIS(num,n);
        int ma=0;
        for(int i=n-1; i>=0; i--)
            ma=max(ma,up[i]);
        for(int i=n-1; i>=0; i--)
        {
            if(up[i]==ma)
            {
                if(help[up[i]]==0)
                    ans[i]=3,ne[ma]=i;
                else
                {
                    ans[i]=2;
                    ans[ne[ma]]=2;
                    ne[ma]=i;
                }
                help[up[i]]=num[i];
            }
            else
            {
                if(num[i]>=help[up[i]+1])
                    ans[i]=1;
                else
                {
                    if(help[up[i]]==0)
                        ans[i]=3,ne[up[i]]=i;
                    else
                    {
                        ans[i]=2;
                        ans[ne[up[i]]]=2;
                        ne[up[i]]=i;
                    }
                    help[up[i]]=num[i];
                }
            }
        }
        for(int i=0; i<n; i++)
            cout<<ans[i];
        cout<<endl;
    }
    return 0;
}
时间: 2024-10-25 20:00:11

486E - LIS of Sequence(LIS)的相关文章

Codeforces 486E LIS of Sequence(线段树+LIS)

题目链接:Codeforces 486E LIS of Sequence 题目大意:给定一个数组,现在要确定每个位置上的数属于哪一种类型. 解题思路:先求出每个位置选的情况下的最长LIS,因为开始的想法,所以求LIS直接用线段树写了,没有改,可以用 log(n)的算法直接求也是可以的.然后在从后向前做一次类似LIS,每次判断A[i]是否小于f[dp[i]+1],这样就可以确定该位 置是否属于LIS序列.然后为第三类的则说明dp[i] = k的只有一个满足. #include <cstdio>

Codeforces Round #277 E. LIS of Sequence(486E) 树状数组乱搞

http://codeforces.com/contest/486/problem/E E. LIS of Sequence time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The next "Data Structures and Algorithms" lesson will be about Longest I

CodeForces 486E LIS of Sequence

题意: n(10^5)个数字的序列a  求每个位置i  它是不出现在任何LIS中  还是  出现在一些LIS中  还是  出现在所有LIS中 思路: 比赛时候唯一没做出的题-  赛后还是不会做- - -b  看了别人的代码觉得好精妙!! 首先以O(nlogn)复杂度求出LIS 然后我们倒序扫描序列a  对于位置i  如果lis[i]=LIS或者a[i]<big[lis[i]+1] (big[x]表示lis=x的a的最大值  这里的意思是  如果a[i]是某个LIS的最后一个  或者  能与某个L

编程之美——longest incremental sequence(LIS)

解法一:通过遍历得到(0:i)的LIS,时间复杂度O(N^2): 具体思路于代码,如下: 1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 5 int longSub(int arr[],int n); 6 7 int main() 8 { 9 int arr[8]={1,-1,2,-3,4,-5,6,-7}; 10 cout<<longSub(arr,8)<<endl; 11

uva 10534 Wavio Sequence LIS

// uva 10534 Wavio Sequence // // 可以将题目转化为经典的LIS. // 从左往右LIS记作d[i],从右往左LIS记作p[i]; // 则最后其中的min(d[i],p[i])就是这个波动序列的一半 // 在这最后的min(d[i],p[i]) * 2 + 1 的最大值就是我们所要求的答案 // // 这题开始想的最后的答案是d[i]==p[i]的时候求最大. // 但是这样是不对的,例如n=4, // 1,3,1,0 // 最长的应该是3,但是我的答案是1,明

【CF486E】LIS of Sequence题解

[CF486E]LIS of Sequence题解 题目链接 题意: 给你一个长度为n的序列a1,a2,...,an,你需要把这n个元素分成三类:1,2,3: 1:所有的最长上升子序列都不包含这个元素 2:有但非所有的最长上升子序列包含这个元素 3:所有的最长上升子序列都包含这个元素 输入格式: 第一行包含一个正整数n,表示序列的长度.第二行包含n个正整数a1,a2,...,an,表示序列中的元素. 输出格式: 一行,包含一个长度为n的.由1,2,3三种数字组成的字符串,第i个数字表示ai所属类

Codeforces 486E LIS of Sequence --树状数组

题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i]表示1~i 的最长递增子序列长度, dp2[i]表示 n~i 的最长递减子序列长度(严格增减),这里我们可以用维护最大值的树状数组来解决,开始还以为要用nlogn求LIS的那种算法,当然那样应该也可以,这里元素值是1~10^5的,可以直接用树状数组,如果元素值任意的话,我们离散化一下也可以用树状数组

Codeforces 486E LIS of Sequence 题解

题目大意: 一个序列,问其中每一个元素是否为所有最长上升子序列中的元素或是几个但不是所有最长上升子序列中的元素或一个最长上升子序列都不是. 思路: 求以每一个元素为开头和结尾的最长上升子序列长度,若两者相加比最长上升子序列长度+1小,则一个也不是:否则若有另一元素与它的两个值完全相同,则不是所有;否则在所有. 代码: 1 #include<map> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace st

hdu 3998 Sequence LIS+最大流

题意:给定一个序列,求最长上升子序长度以及有多少组,每个元素只能用一次. 思路:先求LIS,记为num,求出以每个点为末尾的最长子序列长度.窝们将每个点点拆成i和i',i --> i' 容量为1,源点连接d[ i ]=1的点,容 量为1,汇点连接d[ i ]=num的点,容量为1.对于j<i, a[ j ] < a[ i ],d[ i ] = d[ j ] + 1的情况,j' --> i 连一条容量为1的边,跑最大流即可.详见代码: /***********************