codeforces#323(div2) D. Once Again... 最长不下降子序列

给出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);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值