B. Once Again...
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an array of positive integers a1, a2, ..., an × T of length n × T. We know that for any i > n it is true that ai = ai - n. Find the length of the longest non-decreasing sequence of the given array.

Input

The first line contains two space-separated integers: nT (1 ≤ n ≤ 100, 1 ≤ T ≤ 107). The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 300).

Output

Print a single number — the length of a sought sequence.

Examples
input
4 3
3 1 4 2
output
5
Note

The array given in the sample looks like that: 3, 1, 4, 2, 3, 1, 4, 2, 3, 1, 4, 2. The elements in bold form the largest non-decreasing subsequence.

  其实想了好久都不明白网上有人说是插空是怎么回事,现在也不明白。先记下,看以后会不会懂。。。只能泛泛的理解长度为n的序列重复n次应该会出现比较特殊的情况,比如‘循环’什么的。在怎么循环这个重复的序列也只有n个不同的数。t比n大很多,t<=n时直接做不会超时,t很大时,只求到重复n次的lis。之后加上后面原来数列里面出现次数最多的数的次数*(t-n)。可以想象,一个数在原序列里面出现次数越多,最长不下降数列里面它出现的几率和次数应该也是最多的。

实现过程中用到upper_bound()函数,它是求一个数的上界位置,就是比要求的数大的第一个位置,注意这里是大于不是大于等于。比如a[5]={1,2,2,2,5},upper_bound(a,a+5,2)-a=4.(严格来说返回的是数组编号地址)就是比2大的第一个位置下标为4。所以当数组里所有元素都小于等于给定的key的话,它会返回数组最后一个元素的下一个位置的下标,即upper_bound(a,a+5,5)-a=5。而lower_bound()函数是求大于等于当前值的第一个位置,所以lower_bound(a,a+5,2)-a=1,即第一次出现大于等于2的位置下标为1。

非下降子序列和递增有一点的不同就是允许重复。所以用upper_bound()求当前元素的下一个位置,再更新。知道upper_bound()的作用代码就好理解了:

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1e4 + ;
int dp[MAXN];
int num[MAXN], a[];
int re[]; int main()
{
int n, t;
int maxncnt = ;
memset(re, , sizeof(re));
memset(dp, , sizeof(dp));
scanf("%d%d", &n, &t);
for (int i = ; i < n; i++) {
scanf("%d", &a[i]);
re[a[i]]++;
if (re[a[i]] > maxncnt) maxncnt = re[a[i]];
}
int cnt = ;
for (int i = ; i < min(n, t); i++) {
for (int j = ; j < n; j++)
num[cnt++] = a[j];
}
int val = ;
for (int i = ; i < cnt; i++) {
int pos = upper_bound(dp, dp + val, num[i]) - dp;
if (pos == val) dp[val++] = num[i];
else dp[pos] = num[i];
}
if (t > n) val += (t - n)*maxncnt;
printf("%d\n", val);
return ;
}

求非减lis处代码还可以仿照lis求法做下小改动。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1e4 + ;
int dp[MAXN];
int num[MAXN], a[];
int re[],val; int main()
{
int n, t;
int maxncnt = ;
memset(re, , sizeof(re));
memset(dp, , sizeof(dp));
scanf("%d%d", &n, &t);
for (int i = ; i < n; i++) {
scanf("%d", &a[i]);
re[a[i]]++;
if (re[a[i]] > maxncnt) maxncnt = re[a[i]];
}
int cnt = ;
for (int i = ; i < min(n, t); i++) {
for (int j = ; j < n; j++) {
num[cnt++] = a[j];
}
}
int val = ;
dp[] = num[];
for (int i = ; i < cnt; i++) {
if (num[i] >= dp[val - ]) dp[val++] = num[i];
else
{
int pos = upper_bound(dp, dp + val, num[i]) - dp;
dp[pos] = num[i];
}
}
if (t > n) val += (t - n)*maxncnt;
printf("%d\n", val);
return ;
}

我非作死想要自己实现类似upper_bounder()的作用自己写二分,怎么写都不对,但还是有人会写。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1e4 + ;
int dp[MAXN],num[MAXN];
int a[];
int re[], val; int binary_search(int i)
{
int left, right, mid;
left = , right = val;
while (left<right)
{
mid = (left + right) >> ;
if (dp[mid] > num[i]) right = mid;
else left = mid + ;
}
return left;
} int main()
{
int n, t;
int maxncnt = ;
memset(re, , sizeof(re));
memset(dp, , sizeof(dp));
scanf("%d%d", &n, &t);
for (int i = ; i <= n; i++) {
scanf("%d", &a[i]);
re[a[i]]++;
if (re[a[i]] > maxncnt) maxncnt = re[a[i]];
}
int cnt = ;
for (int i = ; i <= min(n, t); i++) {
for (int j = ; j <= n; j++)
num[cnt++] = a[j];
}
val = ;
dp[] = num[];
for (int i = ; i <= cnt; i++) {
if (num[i] >= dp[val])
dp[++val] = num[i];
else {
int pos = binary_search(i);
dp[pos] = num[i];
}
}
printf("%d\n", val + maxncnt*(t - min(n, t)));
return ;
}

另一种二分写法:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
int a[];
int s[];
int m[]; int main()
{
int n,T;
scanf("%d%d",&n,&T);
memset(m,,sizeof(m));
int ansm=;
for(int i=;i<n;i++){
scanf("%d",a+i);
m[a[i]]++;
ansm=max(m[a[i]],ansm);
}
int top=;
for(int i=;i<min(n,T);i++){
for(int j=;j<n;j++){
if(top==||a[j]>=s[top-]){
s[top]=a[j];
top++;
}else{
int l=,r=top-;
int ans=r;
while(l<=r){
int mid=(l+r)>>;
if(s[mid]>a[j]){
ans=mid;
r=mid-;
}else{
l=mid+;
}
}
s[ans]=a[j];
}
}
}
printf("%d\n",top+ansm*(T-min(n,T)));
return ;
}

Codeforces Round #323 (Div. 2) Once Again... CodeForces - 582B 最长非下降子序列【dp】(不明白)的更多相关文章

  1. Codeforces Round #323 (Div. 2) D. Once Again... 暴力+最长非递减子序列

                                                                                  D. Once Again... You a ...

  2. Educational Codeforces Round 97 (Rated for Div. 2) E. Make It Increasing(最长非下降子序列)

    题目链接:https://codeforces.com/contest/1437/problem/E 题意 给出一个大小为 \(n\) 的数组 \(a\) 和一个下标数组 \(b\),每次操作可以选择 ...

  3. Codeforces Round #323 (Div. 2) D. Once Again... 乱搞+LIS

    D. Once Again... time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  4. Codeforces Round #205 (Div. 2)C 选取数列可以选择的数使总数最大——dp

    http://codeforces.com/contest/353/problem/C Codeforces Round #205 (Div. 2)C #include<stdio.h> ...

  5. Codeforces Round #323 (Div. 1) B. Once Again... 暴力

    B. Once Again... Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/582/probl ...

  6. Codeforces Round #323 (Div. 2) C. GCD Table 暴力

    C. GCD Table Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/583/problem/C ...

  7. 重复T次的LIS的dp Codeforces Round #323 (Div. 2) D

    http://codeforces.com/contest/583/problem/D 原题:You are given an array of positive integers a1, a2, . ...

  8. Codeforces Round #323 (Div. 2) C. GCD Table map

    题目链接:http://codeforces.com/contest/583/problem/C C. GCD Table time limit per test 2 seconds memory l ...

  9. Codeforces Round #323 (Div. 2) C.GCD Table

    C. GCD Table The GCD table G of size n × n for an array of positive integers a of length n is define ...

随机推荐

  1. Mathtype部分数学符号不能显示,只能显示方框时的解决办法

    解决方法:打开C:\WINDOWS\Fonts,若里面有MT Extra(TrueType)字体或其快捷方式,则将其删除,再把MathType安装目录下\MathType 6.0\Fonts\True ...

  2. Sublime keymap 个性修改

    [ // 保存全部 {"keys": ["ctrl+alt+s"], "command": "save_all"}, / ...

  3. PhpExcel参考网址

    参考网址: http://www.cnblogs.com/yuwensong/p/3771787.html

  4. 在 IE 选项那提示 ”某些设置由系统管理员进行管理” 解决

    运行 regedit 打开注册表 修改注册表值HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Interne ...

  5. 根据网站运行日志猜测的百度蜘蛛ip

    da大部分文章都是吵来吵去,不准确 所以就不参考那些沙雕的文章了,直接自己统计一个 123.125.71.117 123.125.71.58 220.181.108.115 220.181.108.1 ...

  6. 洛谷 P1004 方格取数 【多线程DP/四维DP/】

    题目描述(https://www.luogu.org/problemnew/show/1004) 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0. ...

  7. Comparator进行List集合排序

    对数据库中查询到的结果进行排序,一般开发中,实体类是没有实现Comparable接口的,所以不能实现compareTo()方法进行排序, 只能用Comparator去进行排序,只需要在带排序的集合中加 ...

  8. Leetcode606.Construct String from Binary Tree根据二叉树创建字符串

    你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串. 空节点则用一对空括号 "()" 表示.而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空 ...

  9. JavaScript--jquery.min.js文件

    /*! jQuery v1.12.3 | (c) jQuery Foundation | jquery.org/license */ !function(a,b){"object" ...

  10. WPF Popup实现拖动

    问题一.popup总是置顶,遮挡其他窗口 最近发现popup设置打开后,总是会遮挡其他窗口,而我们只想让它仅仅在应用程序的上一层即可,并不像让它在最上面 解决方案是继承Popup重新定义控件Popup ...