B. Once Again…
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array of positive integers a1, a2, …, an × T of length n × T. We know that for any i > n it is true that ai = ai - n. Find the length of the longest non-decreasing sequence of the given array.
Input
The first line contains two space-separated integers: n, T (1 ≤ n ≤ 100, 1 ≤ T ≤ 107). The second line contains n space-separated integers a1, a2, …, an (1 ≤ ai ≤ 300).
Output
Print a single number — the length of a sought sequence.
Sample test(s)
input
4 3
3 1 4 2
output
5
Note
The array given in the sample looks like that: 3, 1, 4, 2, 3, 1, 4, 2, 3, 1, 4, 2. The elements in bold form the largest non-decreasing subsequence.
题意,要求循环数列的最长非递增子序列。
如果,周期是足够大的(大于 2 * n),那么怎样才能最长呢,无疑会出现中间有一段是平的,也就是一个周期内出现次数最多的那个数。因为,一个周期最多有n个不同的数,要求的数列又是递增的,达到n个后,还有更多的,肯定是有重复的数。
就像如图所示
所示的n1 n2最长是n段周期。所以,我们可以先把前n * n个数,后n * n 个数算出最长非严格递增子序列。中间那段就是,一个周期出现最多的次数* (T - 2 * n);
时间复杂度为n * n log (n * n);
下面用两种方式求,
第一种,直接用dp推,由于是周期的数列,所以,可以优化到o(n * n * n)的复杂度。
第二种,就直接用二分查找的方法,优化求非递增子序列的方法。
主要思想就是,用一个数组维护一个递增的子序列,如果,新加的无素大于,最后一个无素,直接加入,否则,在数组里,把第一个大于新加的元素的元素更新就可以了。复杂度为o(n * n * log(n * n));
#define N 100005
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,T,dp[N],num[400],b[N],a[N],an;
int Find2(int bn){
FI(bn) dp[i] = 1;
int maxx = 0;
FI(bn){
int s = min(i,n);
for(int j = 1;j<=s;j++){
if(b[i - j] <= b[i]){
dp[i] = max(dp[i],dp[i - j] + 1);
}
}
maxx = max(maxx,dp[i]);
}
return maxx;
}
int Find1(int bn){
an = 0;
FI(bn){
if(an <= 0 || b[i] >= a[an - 1]){
a[an++] = b[i];
}
else {
int k = (upper_bound(a,a+an,b[i]) - a);
a[k] = b[i];
}
}
return an;
}
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(S2(n,T)!=EOF)
{
fill(num,0);
int mn = 0;
FI(n){
S(b[i]);
num[b[i]]++;
mn = max(mn,num[b[i]]);
}
if(T <= 2 * n){
int bn = n * T;
FI(bn){
b[i] = b[i % n];
}
printf("%d\n",Find1(bn));
}
else {
int bn = n * 2 * n;
FI(bn){
b[i] = b[i % n];
}
printf("%d\n",mn * (T - 2 * n) + Find1(bn));
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}