CF 277 Div2 E LIS of Sequence
2015-01-18 00:15
441 查看
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 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) elementsa1, a2, ..., an
(1 ≤ ai ≤ 105). A subsequence
ai1, ai2, ..., aik
where 1 ≤ i1 < i2 < ... < ik ≤ n is called increasing ifai1 < 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 indexesi (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 onebut 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 sequencea.
The second line contains n space-separated integersa1, 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 indexi belongs to.
Sample test(s)
Input
Output
Input
Output
Input
Output
Note
In the second sample, sequence a consists of 4 elements:{a1, a2, a3, a4}
={1, 3, 2, 5}. Sequence a has exactly 2 longest increasing subsequences of length 3, they are{a1, a2, a4}
={1, 3, 5} and {a1, a3, a4} ={1, 2, 5}.
In the third sample, sequence a consists of 4 elements:{a1, a2, a3, a4}
={1, 5, 2, 3}. Sequence a have exactly 1 longest increasing subsequence of length 3, that is{a1, a3, a4}
={1, 2, 3}.
解析
LIS问题,先从前往后跑一个最长上升子序列L,再从后往前跑一个最长下降子序列R。其实从前往后看两者都是上升的,注意L[i]<>R[i]。
对于第一类始终不在LIS中的,一定有L[i]+R[i]-1<maxl(其中maxl是最长上升子序列)。
除开第一类看,L[i]只出现过一次的是第三类,多次的是第二类。
一定要用O(nlogn)的动规(新技能get)讲解
题目:
给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,
a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。要求时间复杂度O(nlgn)
这也是一道动态规划的经典应用。一种动态规划的状态表示描述为:m[i],1≤i≤n,表示以x[i]结尾的最长上升子序列的长度,则问题的解为 max{m[i],1≤i≤n},状态转移方程和边界条件为:
m[i]=1+max{0, m[k]|x[k]<x[i] , 1≤k<i }同时当m[i]>1时,令p[i]=k,表示最优决策,
以便在计算出最优值后构造最长单调上升子序列。
上述算法的状态总数为O(n),每个状态转移的状态数最多为O(n),每次状态转移的时间为
O(1),所以算法总的时间复杂度为O(n2)。
我们先来考虑以下两种情况:
1、若x[i]<x[j],m[i]=m[j],则m[j]这个状态不必保留。因为,可以由状态m[j]转移得到
的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到;另一方面,
可以由状态m[i]转移得到的状态m[k] (k>j,k>i),当x[j]>x[k]>x[i]时,m[k]就无法由m
[j]转移得到。
由此可见,在所有状态值相同的状态中,只需保留最后一个元素值最小的那个状态即可。
2、若x[i]<x[j],m[i]>m[j],则m[j]这个状态不必保留。因为,可以由状态m[j]转移得到的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到,而且m[i]>m[j],所以m[k]≥m[i]+1>m[j]+1,则m[j]的状态转移是没有意义的。
综合上述两点,我们得出了状态m[k]需要保留的必要条件:不存在i使得:x[i]<x[k]且m[i]≥m[k]。
于是,我们保留的状态中不存在相同的状态值,且随着状态值的增加,最后一个元素的值
也是单调递增的。
也就是说,设当前保留的状态集合为S,则S具有以下性质D:
对于任意i∈S, j∈S, i≠j有:m[i]≠m[j],且若m[i]<m[j],则x[i]<x[j],否则x[i]>x[j]。
下面我们来考虑状态转移:假设当前已求出m[1..i-1],当前保留的状态集合为S,下面计
算m[i]。
1、若存在状态k∈S,使得x[k]=x[i],则状态m[i]必定不需保留,不必计算。因为,不妨
设m[i]=m[j]+1,则x[j]<x[i]=x[k],j∈S,j≠k,所以m[j]<m[k],则m[i]=m[j]+1≤m[k],所以状态m[i]不需保留。
2、否则,m[i]=1+max{m[j]| x[j]<x[i], j∈S}。我们注意到满足条件的j也满足x[j]=max{x[k]|x[k]<x[i], k∈S}。同时我们把状态i加入到S中。
3、若2成立,则我们往S中增加了一个状态,为了保持S的性质,我们要对S进行维护,若存
在状态k∈S,使得m[i]=m[k],则我们有x[i]<x[k],且x[k]=min{x[j]|x[j]>x[i], j∈S}。于是状态k应从S中删去。
于是,我们得到了改进后的算法:
For i:=1 to n do
{
找出集合S中的x值不超过x[i]的最大元素k;
if x[k]<x[i] then
{
m[i]:=m[k]+1;
将状态i插入集合S;
找出集合S中的x值大于x[i]的最小元素j;
if m[j]=m[i] then 将状态j从S中删去;
}
}
从性质D和算法描述可以发现,S实际上是以x值为关键字(也是以m值为关键字)的有序集
合。
若使用平衡树实现有序集合S,则该算法的时间复杂度为O(n*log2n)。(每个状态转移的状
态数仅为O(1),
而每次状态转移的时间变为O(log2n))
还有就是从后往前跑一个最长下降子序列的时候,要在一个单减的数列里用lower_bound,有个小小的技巧,在每个数前面加个负号就变成单增的了。
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 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) elementsa1, a2, ..., an
(1 ≤ ai ≤ 105). A subsequence
ai1, ai2, ..., aik
where 1 ≤ i1 < i2 < ... < ik ≤ n is called increasing ifai1 < 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 indexesi (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 onebut 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 sequencea.
The second line contains n space-separated integersa1, 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 indexi belongs to.
Sample test(s)
Input
1 4
Output
3
Input
4 1 3 2 5
Output
3223
Input
4
1 5 2 3
Output
3133
Note
In the second sample, sequence a consists of 4 elements:{a1, a2, a3, a4}
={1, 3, 2, 5}. Sequence a has exactly 2 longest increasing subsequences of length 3, they are{a1, a2, a4}
={1, 3, 5} and {a1, a3, a4} ={1, 2, 5}.
In the third sample, sequence a consists of 4 elements:{a1, a2, a3, a4}
={1, 5, 2, 3}. Sequence a have exactly 1 longest increasing subsequence of length 3, that is{a1, a3, a4}
={1, 2, 3}.
解析
LIS问题,先从前往后跑一个最长上升子序列L,再从后往前跑一个最长下降子序列R。其实从前往后看两者都是上升的,注意L[i]<>R[i]。
对于第一类始终不在LIS中的,一定有L[i]+R[i]-1<maxl(其中maxl是最长上升子序列)。
除开第一类看,L[i]只出现过一次的是第三类,多次的是第二类。
一定要用O(nlogn)的动规(新技能get)讲解
题目:
给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,
a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。要求时间复杂度O(nlgn)
这也是一道动态规划的经典应用。一种动态规划的状态表示描述为:m[i],1≤i≤n,表示以x[i]结尾的最长上升子序列的长度,则问题的解为 max{m[i],1≤i≤n},状态转移方程和边界条件为:
m[i]=1+max{0, m[k]|x[k]<x[i] , 1≤k<i }同时当m[i]>1时,令p[i]=k,表示最优决策,
以便在计算出最优值后构造最长单调上升子序列。
上述算法的状态总数为O(n),每个状态转移的状态数最多为O(n),每次状态转移的时间为
O(1),所以算法总的时间复杂度为O(n2)。
我们先来考虑以下两种情况:
1、若x[i]<x[j],m[i]=m[j],则m[j]这个状态不必保留。因为,可以由状态m[j]转移得到
的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到;另一方面,
可以由状态m[i]转移得到的状态m[k] (k>j,k>i),当x[j]>x[k]>x[i]时,m[k]就无法由m
[j]转移得到。
由此可见,在所有状态值相同的状态中,只需保留最后一个元素值最小的那个状态即可。
2、若x[i]<x[j],m[i]>m[j],则m[j]这个状态不必保留。因为,可以由状态m[j]转移得到的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到,而且m[i]>m[j],所以m[k]≥m[i]+1>m[j]+1,则m[j]的状态转移是没有意义的。
综合上述两点,我们得出了状态m[k]需要保留的必要条件:不存在i使得:x[i]<x[k]且m[i]≥m[k]。
于是,我们保留的状态中不存在相同的状态值,且随着状态值的增加,最后一个元素的值
也是单调递增的。
也就是说,设当前保留的状态集合为S,则S具有以下性质D:
对于任意i∈S, j∈S, i≠j有:m[i]≠m[j],且若m[i]<m[j],则x[i]<x[j],否则x[i]>x[j]。
下面我们来考虑状态转移:假设当前已求出m[1..i-1],当前保留的状态集合为S,下面计
算m[i]。
1、若存在状态k∈S,使得x[k]=x[i],则状态m[i]必定不需保留,不必计算。因为,不妨
设m[i]=m[j]+1,则x[j]<x[i]=x[k],j∈S,j≠k,所以m[j]<m[k],则m[i]=m[j]+1≤m[k],所以状态m[i]不需保留。
2、否则,m[i]=1+max{m[j]| x[j]<x[i], j∈S}。我们注意到满足条件的j也满足x[j]=max{x[k]|x[k]<x[i], k∈S}。同时我们把状态i加入到S中。
3、若2成立,则我们往S中增加了一个状态,为了保持S的性质,我们要对S进行维护,若存
在状态k∈S,使得m[i]=m[k],则我们有x[i]<x[k],且x[k]=min{x[j]|x[j]>x[i], j∈S}。于是状态k应从S中删去。
于是,我们得到了改进后的算法:
For i:=1 to n do
{
找出集合S中的x值不超过x[i]的最大元素k;
if x[k]<x[i] then
{
m[i]:=m[k]+1;
将状态i插入集合S;
找出集合S中的x值大于x[i]的最小元素j;
if m[j]=m[i] then 将状态j从S中删去;
}
}
从性质D和算法描述可以发现,S实际上是以x值为关键字(也是以m值为关键字)的有序集
合。
若使用平衡树实现有序集合S,则该算法的时间复杂度为O(n*log2n)。(每个状态转移的状
态数仅为O(1),
而每次状态转移的时间变为O(log2n))
还有就是从后往前跑一个最长下降子序列的时候,要在一个单减的数列里用lower_bound,有个小小的技巧,在每个数前面加个负号就变成单增的了。
#include<cstdio> #include<algorithm> #include<set> #include<cstring> using namespace std; #define LOCAL #define INF 0x3f3f3f3f int L[100100],R[100100],g[100100],N,Arr[100100],ans[100100],cnt[100100],maxl;//dp[i] is method void Dynamic_Planning() { maxl=0; //最长上升子序列 memset(g,0x3f,sizeof(g)); for(int i=1;i<=N;i++) { int k=lower_bound(g+1,g+N+1,Arr[i])-g; L[i]=k; if(g[k]==INF) maxl++; g[k]=Arr[i]; } //最长下降子序列 memset(g,0x3f,sizeof(g)); for(int i=N;i>0;i--) { int k=lower_bound(g+1,g+N+1,-Arr[i])-g; R[i]=k; g[k]=-Arr[i]; } #ifdef LOCA printf("%d\nL:",maxl); for(int i=1;i<=N;i++) printf("%d ",L[i]); puts(""); printf("R:"); for(int i=1;i<=N;i++) printf("%d ",R[i]); puts(""); #endif } void write() { memset(ans,0,sizeof(ans)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=N;i++) if(L[i]+R[i]<maxl+1) ans[i]=1; else cnt[L[i]]++; for(int i=1;i<=N;i++) if(ans[i]) printf("%d",ans[i]); else if(cnt[L[i]]==1) printf("3"); else printf("2"); printf("\n"); } int main() { #ifdef LOCAL freopen("C.in","r",stdin); #endif while(scanf("%d",&N)==1) { for(int i=1;i<=N;i++) L[i]=R[i]=1,scanf("%d",&Arr[i]); Dynamic_Planning(); write(); } #ifdef LOCAL while(1); #endif return 0; }
相关文章推荐
- CF 277 div2 A. Calculating Function
- CF round 277 (div2) D题 树形dp
- CF 196 Div 2 D (树形dp)
- CF 246 div2 D Prefixes and Suffixes (所有前缀的出现次数)
- Codeforces Round #397 (Div. 1 + Div. 2 combined) 题解(CF765A,CF765B,CF765C,CF765D,CF765E,CF765F)
- (补题)CF 467 div2
- CF#FF (Div. 2) C.
- cf--------(div1)1A. Theatre Square
- CF-Codeforces Round #410 (Div. 2)-A~C
- cf #360 div2 D-Remainders Game(中国剩余定理)
- CF_Round274_Div1_B_Long Jump_二分搜索
- CF Div211 (C)
- CF Round# 449 Div2 B. Chtholly's request
- 【CF】174 Div.1 B Cow Program
- 【CF】142 Div.1 B. Planes
- CF 159 div2 d
- CF 92 div2 B
- cf 193 div2 A. Down the Hatch!
- CF Beta Round #89 (Div. 2) - Caesar's Legions
- CF——Codeforces Round #428 (Div. 2)C. Journey