[DP]Codeforces Round #323 (Div. 2)DOnce Again...

本文探讨了一种经典的动态规划问题——寻找最长不下降子序列的优化方案。针对序列重复多次的情况,通过分析序列特点,提出了高效的算法实现,并讨论了其中的误区与解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
给出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);
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值