给出n个数,求循环T次后的最长不下降子序列
由于T很大,直接模拟是不可取的,但是自己试几次就发现,其实要求的子序列是由
一段不重复的序列 + 重复序列 + 一段不重复的序列
或者 重复序列 + 一段不重复的序列
或者 一段不重复的序列
这样循环的“最长不下降子序列”一定会在n次循环里出现,然后再把后面(T- n)次循环里的重复序列插进最长不下降子序列中间就能构成结果(当T>n)
(最坏情况为:5 4 3 2 这种单调递减的序列,循环4次也能找到他的“最长不下降子序列”)
用O(nlogn)求最长不下降子序列
#include<stdio.h>
#define ll long long
const int N = 10010;
int a[N], f[N], d[N], cnt[305];
int max(int a, int b) {return a>b?a:b;}
int bsearch(const int *f, int size, const int &a)
{
int l = 0, r = size - 1;
while(l <= r)
{
int mid = (l+r)>>1;
if(a >= d[mid-1] && a < d[mid])
return mid;
else if(a < d[mid])
r = mid-1;
else l = mid+1;
}
}
int LIS(const int *a, int n, int T)
{
int i, j, size = 1;
d[0] = a[0]; f[0] = 1;
for(i = 1;i < n*n&&i < T*n;++i)
{
int ii = i % n;
if(a[ii] < d[0])
j = 0;
else if(a[ii] >= d[size-1])
j = size++;
else
j = bsearch(d, size, a[ii]);
d[j] = a[ii]; f[i] = j+1;
}
return size;
}
int main()
{
int i, n, T, max_cnt;
ll res;
max_cnt = 0;
scanf("%d %d", &n, &T);
for(i = 0;i < n;++i){
scanf("%d", &a[i]);
cnt[a[i]]++;
max_cnt = max(max_cnt, cnt[a[i]]);
}
res = LIS(a, n, T);
if(T*n > n*n) res += (T - n)*max_cnt;
if(n == 1) res = T;
printf("%d\n", res);
}