Codeforces Round #277 (Div. 2)E题

来源:互联网 发布:shake it是什么意思 编辑:程序博客网 时间:2024/05/16 14:02

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:

  1. group of all i such that ai belongs to no longest increasing subsequences.
  2. group of all i such that ai belongs to at least one but not every longest increasing subsequence.
  3. 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 ibelongs to.

Sample test(s)
input1
1
4
output1
3
input2
4
1 3 2 5
output2
3223
input3
4
1 5 2 3
output3
3133
题目大意:给你一个数字序列,先求最长不小降子序列。然后将序列中的数字分为3类,第一类:ai不属于最长子序列;第二类:ai属于最长子序列但不属于每一个最长子序列;第三类:ai属于每一个最长子序列。
题目分析:先用O(nlogn)求出到每一个数时的最长序列,然后处理分类情况。姿势:逆序扫一遍,记录后面最长子序列为j时的最大的数(放松条件),将属于最长子序列的条件最‘松’化,这样就可以将第一类和二三类分开。然后在扫一遍记录属于二三类的数,将长度唯一(长度为j只有这一个数)的记录下来,这些介绍关键路径了(第三类)。

#include<cstdio>#include<cstring>int a[100100],f[100100],e[100100],g[100100],h[100100],ans[100100];int find_mid(int l,int r, int a){    int mid;    if (r-l<2) return l;    mid=(l+r)/2;    if (h[mid]>a) return find_mid(l,mid,a);    else return find_mid(mid,r,a);}int main(){    int i,k,n,mid,maxx;    scanf("%d", &n);    for (i=1;i<=n;i++) ans[i]=1;    memset(g,0,sizeof(g));    memset(f,0,sizeof(f));    memset(e,0,sizeof(e));    for (i=1;i<=n;i++) scanf("%d", &a[i]);    k=1;f[1]=1;h[1]=a[1];    for (i=2;i<=n;i++)    if (a[i]>h[k]) {        k++;f[i]=k;        h[k]=a[i];    } else {        if (a[i]==h[k]) f[i]=k;        else {            mid=find_mid(1,k,a[i]);            if (a[i]==h[mid]||a[i]<h[mid]) {                f[i]=mid;h[mid]=a[i];            } else {                f[i]=mid+1;h[mid+1]=a[i];            }        }    }    maxx=0;    for (i=1;i<=n;i++)    if (f[i]>maxx) maxx=f[i];    e[maxx+1]=200000;    for (i=n;i>0;i--)    if (a[i]<e[f[i]+1]) {        ans[i]=2;        if (a[i]>e[f[i]]) e[f[i]]=a[i];    }    for (i=1;i<=n;i++)    if (ans[i]==2) g[f[i]]++;    for (i=1;i<=n;i++)    if (ans[i]==2&&g[f[i]]==1) ans[i]=3;    for (i=1;i<=n;i++) printf("%d",ans[i]);    printf("\n");    return 0;}
0 0