Once Again...

Once Again...

题目链接

题意

给n个数,然后T次循环后组成一个新的数列,求这个数列的最长不递减子序列。

思路

因为最多就100个元素,所以当m<=100的时候直接暴力求最长不递减子序列,然后当m>=100的时候,因为每个循环节最少可以取1个元素,所以只要100个循环节就可以包括所有的数,然后再往里面插入剩下的一个在当前路径下在每段重复有最多的元素,也就是\((m-100)*cnt[k]\)(k就是那个数);复杂度(\(n^2\));

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
int a[100005];
int dp[100005];
int cnt[100005];
int id[100005];
int main(void)
{
   int n,m;
   scanf("%d %d",&n,&m);
   for(int i = 0;i < n;i++)
      scanf("%d",&a[i]);
   int maxx  = 1;
   if(m <= 100)
   {
       for(int i = n;i < n*m;i++)
       {
           a[i] = a[i-n];
       }
       dp[0] = 1;
       for(int i = 1;i < n*m;i++)
       {   dp[i] = 1;
           for(int j = 0;j < i;j++)
           {
               if(a[i] >= a[j])
                dp[i] = max(dp[j] + 1,dp[i]);
           }
           maxx = max(maxx,dp[i]);
       }
   }
   else
   {
       for(int i = n;i < n*100;i++)
           a[i] = a[i-n];
       for(int i = 0;i < n;i++)
         cnt[a[i]]++;
       dp[0] = 1;
       for(int i = 1;i < n*100;i++)
       {   dp[i] = 1;
           for(int j = 0;j < i;j++)
           {
               if(a[i] >= a[j])
                {
                    if(dp[i] < dp[j] + 1)
                    {
                        dp[i] = dp[j] + 1;
                        id[i] = j;
                    }
                }
           }
           int c = i;
           while(c!=0)
           maxx = max(maxx,dp[i] + (m-100)*cnt[a[c]]),c = id[c];
       }
   }
   printf("%d\n",maxx);
   return 0;
}
posted @ 2017-05-17 19:09  sCjTyC  阅读(211)  评论(0编辑  收藏  举报