CF #323 DIV2 D题

可以知道,当T较大时,对于LIS,肯定会有很长的一部分是重复的,而这重复的部分,只能是一个block中出现次数最多的数字组成一序列。所以,对于T》1000时,可以直接求出LIS,剩下T-=1000直接求出现次数最多的数字的个数即可。其实可以不用到1000,只需到n即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int MAX=105;
int p[MAX*MAX*10];
int a[MAX],n,t,m;
int dp[MAX*MAX*10];

int bin(int l,int r,int key){
	while(l<=r){
		int mid=(l+r)>>1;
		if(dp[mid]>key&&dp[mid-1]<=key) return mid;
		if(dp[mid]>key) r=mid-1;
		else l=mid+1;
	}
	return 1;
}

int LIS(int len){
	int res=1; dp[res]=p[1];
	for(int i=2;i<=len;i++){
		if(p[i]>=dp[res]){
			dp[++res]=p[i];
		}
		else{
			int pos=bin(1,res,p[i]);
			dp[pos]=p[i];
		}
	}
	///cout<<res<<endl;
	return res;
}

void slove(int l){
	int ans=LIS(l);
///	cout<<ans<<endl;
	sort(a+1,a+1+n);
	int counts=1,maxlen=1;
	for(int i=2;i<=n;i++){
		if(a[i]==a[i-1]) counts++;
		else{
			if(counts>maxlen) maxlen=counts;
			counts=1;
		}
	}
	if(counts>maxlen) maxlen=counts;
	printf("%d
",ans+(t-m)*maxlen);
}

int main(){
	while(scanf("%d%d",&n,&t)!=EOF){
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		m=min(1000,t);
		dp[0]=-1e9+7;
		for(int i=0;i<m;i++){
			for(int j=1;j<=n;j++){
				p[i*n+j]=a[j];
				dp[i*n+j]=1e9+7;
			}
		}
		slove(m*n);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4856550.html