题意:
给出n,t,表示n个数的序列重复t次,求出最长不下降子序列的长度。
分析:
经典DP的改良。脑子里想的就是重复够一定次数后,肯定就会出现重复的情况。
刚开始想的是最后加入的数是一直重复的,可能有多个数,比如 270 298 ,298加进来增加长度,270加进来可以覆盖298,那么最后的那个数还是270.这里犯了一个错误,270加进来并没有改变子序列的长度,所以无贡献。
还有一点,最后的那个数是最大的数,还是个数最多的那个数呢?
其实这是一个误区,一直循环的不一定是最后加入的那个数,而是数量最多的那个数一直在中间某个部位出现。就好像你只计算一段,然后剩下的那些没计算的就直接插入中间合适的位置就ok了。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <fstream>
#include <math.h>
#include <iomanip>
#define read freopen("q.in","r",stdin)
using namespace std;
typedef long long LL;
#define inf 0x3fffffff
typedef pair<int, int> pii;
const int maxn = 503;
int a[maxn*maxn],d[maxn*maxn];
int c[maxn];
int main()
{
//read;
int n,t,i,j;
while(~scanf("%d%d",&n,&t))
{
int ma=0;
memset(d,0,sizeof(d));
memset(c,0,sizeof(c));
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
c[a[i]]++;
ma=max(ma,c[a[i]]);
}
int res=0;
if(t>n)
{
res+=(t-n)*ma;
t=n;
}
for(i=n;i<n*t;i++)a[i]=a[i-n];
int cnt=1;
d[cnt]=a[0];
for(i=1;i<n*t;i++)
{
if(a[i]>=d[cnt])
d[++cnt]=a[i];
else
{
int p=upper_bound(d,d+cnt+1,a[i])-d;
if(p==cnt+1)continue;
else d[p]=a[i];
}
}
printf("%d\n",cnt+res);
}
}