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. Leetcode105. Construct Binary Tree from Preorder and Inorder Traversal前序与中序构造二叉树

    根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15 ...

  2. CentOS 6.5之zabbix2.2的简单部署

    Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.(目前,官方长期维护的稳定版本有2.2和3.0) 其他常见的监控工具还有: (1)Cacti:Cacti是一 ...

  3. 使用jquery封装一个可以复用的提示框

    首先在html中 <div class="backcap"> <div class="diolag"> <div class=&q ...

  4. JavaScript多继承(转载)

    js里是否有多继承,如何实现多继承.在这里可以看看java是如何处理多继承的问题,java里是没有多继承的,即一个子类不能同时继承多个父类,但可以实现多个接口,这也间接的实现了多继承.主要是因为多继承 ...

  5. Hackerrank--Emma and sum of products (FFT)

    题目链接 Emma is really fond of integers and loves playing with them. Her friends were jealous, and to t ...

  6. jq写tab切换

    $('.index-news-sub-box ul li').click(function(){ var i=$(this).index(); var img=$('.index-news-img-b ...

  7. CesiumLab V1.2 新功能 倾斜数据处理

    一转眼又是一周的时间,我们的实验室功能又强大了. 照旧我们先放毒,放图,图,太晚了,字都敲不到一起了   lod以及包围盒   大雁塔实例,按楼层单体化   倾斜数据处理参数设置 简单介绍一下 Ces ...

  8. neo4j遍历和图算法

    阅读更多 这篇blog主要和大家分享一下neo4j中是如何对节点进行遍历,和其中集成的图论的一些常用算法. 遍历 http://docs.neo4j.org.cn/tutorials-java-emb ...

  9. web前端学习(二)html学习笔记部分(2)-- 改良的元素(input元素等等)

    1.2.5  HTML5 改良的 input 元素的种类 1.2.5.1  新增的input元素种类中的改良与增加 input 元素的种类 (1) 新增的input元素种类中的url类型.email类 ...

  10. Node.js模拟发起http请求从异步转同步的5种方法

    使用Node.js模拟发起http请求很常用的,但是由于Node模块(原生和第三方库)提供里面的方法都是异步,对于很多场景下应用很麻烦,不如同步来的方便.下面总结了几个常见的库API从异步转同步的几种 ...