Codeforces Round #277 (Div. 2) E. LIS of Sequence DP

E. LIS of Sequence

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://codeforces.com/contest/486/problem/E

Description

The next "Data Structures and Algorithms" lesson will be about Longest Increasing Subsequence (LIS for short) of a sequence. For better understanding, Nam decided to learn it a few days before the lesson.

Nam created a sequence a consisting of n (1 ≤ n ≤ 105) elements a1, a2, ..., an (1 ≤ ai ≤ 105). A subsequence ai1, ai2, ..., aik where 1 ≤ i1 < i2 < ... < ik ≤ n is called increasing if ai1 < ai2 < ai3 < ... < aik. An increasing subsequence is called longest if it has maximum length among all increasing subsequences.

Nam realizes that a sequence may have several longest increasing subsequences. Hence, he divides all indexes i (1 ≤ i ≤ n), into three groups:

    group of all i such that ai belongs to no longest increasing subsequences.
    group of all i such that ai belongs to at least one but not every longest increasing subsequence.
    group of all i such that ai belongs to every longest increasing subsequence.

Since the number of longest increasing subsequences of a may be very large, categorizing process is very difficult. Your task is to help him finish this job.

Input

The first line contains the single integer n (1 ≤ n ≤ 105) denoting the number of elements of sequence a.

The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 105).

Output

Print a string consisting of n characters. i-th character should be '1', '2' or '3' depending on which group among listed above index i belongs to.

Sample Input

4
1 3 2 5

Sample Output

3223

HINT

题意

给你n个数

然后问你这里面的每个数,是否是

1.不属于任何最长上升子序列中

2.属于多个最长上升子序列中

3.唯一属于一个最长上升子序列中

题解:

对于每一个数,维护两个dp

dp1表示1到i的最长上升子序列长度

dp2表示从n到i最长递减子序列长度

然后如果dp1[i]+dp2[i] - 1 == lis ,就说明属于lis里面,如果dp1[i]的值是唯一的,就说明唯一属于一个lis

否则就不属于咯

代码

#include<iostream>
#include<stdio.h>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
int b[maxn];
int a[maxn];
void add(int x,int val)
{
    while(x<=100000)
    {
        b[x] = max(b[x],val);
        x += x & (-x);
    }
}
int get(int x)
{
    int ans = 0;
    while(x)
    {
        ans = max(ans,b[x]);
        x -= x & (-x);
    }
    return ans;
}
int dp1[maxn];
int dp2[maxn];
int ans[maxn];
map<int,int> H;
int main()
{
    int n;scanf("%d",&n);
    int LIS = 0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        dp1[i] = 1 + get(a[i]-1);
        add(a[i],dp1[i]);
        LIS = max(LIS,dp1[i]);
    }
    reverse(a+1,a+1+n);
    memset(b,0,sizeof(b));
    for(int i=1;i<=n;i++)
    {
        a[i] = 100000 - a[i] + 1;
        dp2[i] = 1 + get(a[i] - 1);
        add(a[i],dp2[i]);
    }
    reverse(dp2+1,dp2+1+n);
    for(int i=1;i<=n;i++)
    {
        if(dp1[i]+dp2[i]-1!=LIS)ans[i]=1;
        else H[dp1[i]]++;
    }
    for(int i=1;i<=n;i++)
    {
        if(ans[i]!=1&&H[dp1[i]]==1)
        {
            ans[i]=3;
        }
    }
    for(int i=1;i<=n;i++)
        if(ans[i]==1)
            cout<<"1";
        else if(ans[i]==0)
            cout<<"2";
        else if(ans[i]==3)
            cout<<"3";
}
/*
10
2 2 2 17 8 9 10 17 10 5
*/
原文地址:https://www.cnblogs.com/qscqesze/p/4908665.html