今天想把这道藏了1年的题写完,就顺便把相关算法看了一下。

包括3部分代码:LIS O(n^2)的写法 LIS O(nlogn)的写法送命题:codeforces714E 代码

叫送命题是因为这是去年打网络赛期间的一道集训题,当时没公布题号,就放下了,后来遇到了好多类似的题,都GG了,终于在前几天找到了这道题,果断决定写一写,发现是一道DP+LIS的题目,就把相关代码一起贴出来吧。

LIS

最长上升子序列。例如序列:5 1 2 6 4 7 LIS序列可以为:1 2 4 7长度为4。

LIS O(n^2)的写法

其实很简单,就是一个简单的DP,思路自行百度。

代码:

#include<bits/stdc++.h>
using namespace std;int LIS(int a[],int len)
{if(len==0)return 0;int *dp=new int[len];for(int i=0;i<len;i++) dp[i]=1;for(int i=1;i<len;i++)for(int j=0;j<i;j++)if( a[j] < a[i] )dp[i]=max(dp[i],dp[j]+1);int ans=1;for(int i=0;i<len;i++)ans=max(ans,dp[i]);return ans;
}
int main()
{int n;scanf("%d",&n);int *a = new int[n];for(int i=0;i<n;i++)scanf("%d",&a[i]);printf("%d\n",LIS(a,n));return 0;
}

LIS O(nlogn)的写法

主要是用一个数组s记录dp[i]的对应元素中的最小值,然后从左倒右依次扫描元素数组,对于每个元素在s中找到适合的位置,满足:if(x>=s[slen]) s[slen++]=x;else 找到s[i]>x的第一个位置,s[i]=x;
这种查找位置用2分查找,则时间复杂度就降为O(nlogn),可以这样做的原因自行百度。
需要注意一点:s数组记录的值并不一定就是LIS序列(准确说只有极特殊的情况才是)。

代码:

#Include<bits/stdc++.h>
using namespace std;
int find(int s[],int len,int x)//2分查找
{int a=0,b=len-1,mid;if(x>s[len-1]) return len;while(a<b){mid=(a+b)/2;if(s[mid]<x)a=mid+1;elseb=mid;}if(a==0)return 0;return a;
}
int LIS(int a[],int len)
{if(len==0)return 0;int s[len],slen=1,point;s[0]=a[0];for(int i=1;i<len;i++){point=find(s,slen,a[i]);if(point<slen)s[point]=a[i];else{s[slen]=a[i];slen++;}}return slen;
}int main()
{int A[10001];int len;cin >> len;for(int i=0;i<len;i++)cin >>A[i];cout<<LIS(A, len)<<endl;return 0;
}

codeforces 714E

题目描述:

    Sonya was unable to think of a story for this problem, so here comes the formal description.You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array strictly increasing by making the minimum possible number of operations. You are allowed to change elements in any way, they can become negative or equal to 0.InputThe first line of the input contains a single integer n (1 ≤ n ≤ 3000) — the length of the array.Next line contains n integer ai (1 ≤ ai ≤ 109).OutputPrint the minimum number of operation required to make the array strictly increasing.

题目分析:

简单点说就是给一组数,求最少经过多少次操作使数组满足严格的单调递增,其中每次操作为将一个数+1或-1。ok,我们来想一下,对于一个单调递增数组,应满足以下条件:对于任意i,满足a[i+1]-a[i]>=1;更普通的,对于任意i<j,满足a[j]-a[i]>=j-i;转换一下格式,得到这样的关系:对于任意i<j,满足a[j]-j>=a[i]-i;于是我们只需将a[i]-i这样一个数组变为单调非递减序列。之后将a[i]-i记为数组a,将其排序后的数组记为数组b。
建立一个二维dp数组,dp[n+1][n+1]。
它的一维分量表示得到对第i个元素进行操作的次数。
它的二维分量表示以b[1] ~ b[j]为基准得到ans[1] ~ ans[i]所要进行的操作次数。则dp的每个数据可以由两种方式得到,以dp[i][j]为例:1.dp[i-1][j]+abs(a[i]-b[j]),即利用b[1] ~ b[j]得到a[1] ~ a[i-1]所需要的最小操作数,加利用(且此时只能利用)b[j]为基准得到ans[i]所需要的操作。2.dp[i][j-1],即利用b[1] ~ b[j-1] 得到ans[1] ~ ans[i]所需要的最小操作数。3.特殊的,当j=1时,只能由第一种情况得到。可能这样说比较抽象,我们举个例子。假设最终的a数组为:  2 1则b数组应为:       1 2则可以根据本题思想得到4种结果:以b[1]为基准得到ans数组:ans  1 1以b[2]位基准得到ans数组:ans  2 2以b[1]为基准得到ans[1],以b[2]为基准得到ans[2]:ans  1 2以b[2]为基准得到ans[1],以b[1]为基准得到ans[2]:ans  2 1  //这时是不满足题意的,这也解释了上面括号里的内容。这样,就得到了状态转移方程:dp[i][j] = min{dp[i][j-1] , dp[i-1][j]+abs(a[i]-b[j])};如果你还不明白,没关系,我们用这个方程进行一次解题过程,你就会明白了。仍然用上面的例子:假设最终的a数组为:  2 1则b数组应为:       1 2
1.首先,用b[1]得到ans[1],即将a[1]变为1,则需要进行1次操作;dp[1][1]=1;
2.用b[2]得到ans[1],即将a[1]变为2,需要进行0次操作;
3.用b[1]和b[2]得到ans[1]的最优解,即比较0与1,得到dp[1][2]=min(1,0)=0;
4.用b[1]得到ans[2],即将a[2]变为1,则需要进行0次操作;
5.用b[1]得到ans[1],ans[2]的总操作数为1+0=1,dp[2][1]=1;
6.用b[2]得到ans[2],即将a[2]变为2,则需要进行1次操作;
7.dp[2][2]有两种得到方式:用b[1]得到ans[1],ans[2]的操作数,即dp[2][1];用b[1],b[2]得到ans[1]的最优解的操作数(即dp[1][2])与只能用b[2]得到ans[2]的操作数之和 , 即dp[1][2]+abs(a[1]-b[2]);(因为得到dp[1][2]的结果可能用到了b[2],即将a[1]变成了b[2],则a[2]只能选择变为b[2]或更大的数字)比较这两种方式得到最优解dp[2][2] = min{dp[2][1],dp[1][2]+abs(a[1]-b[2])};
这样dp[2][2]就是我们要求的结果了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3000+5;
long long dp[maxn][maxn];
int a[maxn],b[maxn];
int main()
{int n;scanf("%d",&n);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){scanf("%d",&a[i]);a[i]-=i;b[i]=a[i];}sort(b+1,b+n+1);for(int i=1;i<=n;i++){dp[i][1]=dp[i-1][1]+abs(a[i]-b[1]);for(int j=2;j<=n;j++)dp[i][j]=min( dp[i][j-1] , dp[i-1][j] + abs(a[i]-b[j]) );}printf("%lld\n",dp[n][n]);return 0;
}
到这里,终于将这道题ac了。

一道CF送命题引发的博文相关推荐

  1. 听说「面向对象是怎样工作的?」是一道送命题?| 7月书讯

    简报: 本月图灵计划出品14本图书,包含了6本IT技术图书.2本哈代的数学巨作.3本数学科普书.2本设计类图书.1本职场技能类图书.看看你最期待哪本书?别忘参与文末留言活动哦! 如果你是程序员,那么有 ...

  2. python编程入门 适合于零基础朋友-零基础能学好python吗?教女朋友学python是送命题吗?...

    python近年来的风靡程度就不用小编多说了,大家伙儿都知道,也都想来蹭蹭热度,但蹭着蹭着蹭出问题了:教女朋友学python是送命题吗?教女朋友学python是送命题吗? 近期,网友提出的" ...

  3. 面试中,五大经典“送命题”该如何正确回答?

    疫情下的四月,裁员风波也渐渐平息,各厂hc逐渐放出,计划跳槽的小伙伴开始蠢蠢欲动,受到裁员."双减"风波影响的小伙伴也开始跃跃欲试,是时候为备战"金3银4"找工 ...

  4. 面试时,碰到职场“送命题”该怎么回答?送上这些有求生欲的答案~

    引:作为一个软件测试工程师,每当跳槽换工作时,难免在面试中碰到一些"送命题".之所以称这些问题为"送命题",主要是因为它们:有的知识点很容易混淆:有的问题很难回 ...

  5. 与人斗其乐无穷,教你回答职场送命题!

    职场如战场,人心深似海.没点求生欲,还真没办法在职场好好活下去.跟老板说话要小心翼翼,跟同事说话要谨慎三四,跟客户说话要客客气气,就连跟扫地阿姨说话都要轻声轻气.有时候对方的话里带话,稍微一走神,顿时 ...

  6. 妥善处理的九大面试送命题

    送命题一 请做一个简单的自我介绍吧. 一般回答: 姓名.年龄.爱好(唱,跳,篮球,rap).工作经验,这些在简历上都有.回答要点: 要让面试官从你的介绍中听出你能胜任这份工作.最强技能是什么,在哪方面 ...

  7. EOJ 3344.送命题

    题目链接:EOJ 3344.送命题 题目乍一看以为是斐波那契数列.其实不然. #include <stdio.h> #include <stdlib.h> #include & ...

  8. 手撕 44 道 JavaScript 送命题

    最近有位同学分享给我一个网站,上面列举了 44 道 JavaScript 的送命题,想让我做一下. 对于这种要求我能不满足么,果断开搞哇. 网站地址:http://javascript-puzzler ...

  9. 在软件测试面试中,碰到这些「送命题」,大牛教你一招应对

    前言 作为一个软件测试工程师,每当跳槽换工作时,难免在面试中碰到一些"送命题".之所以称这些问题为"送命题",主要是因为它们:有的知识点很容易混淆:有的问题很难 ...

最新文章

  1. css网页设计实例代码_大型电商平台设计实例:电商平台项目工程、数据库选型、代码库...
  2. 第八次课作业(采购管理、信息与配置管理)
  3. AMD CPU真烂!售后服务也很可恶!
  4. Fiori launchpad里tile的个数是如何从后台取回来的
  5. Ext 与 Jquery 的结合应用
  6. python中字典的用法_Python中字典的详细用法
  7. GPG软件签名与验证
  8. 数模系列(3):模糊综合评价法
  9. 基于51单片机的无线病床呼叫系统装置 proteus仿真原理图程序设计
  10. python opencv 读取图片_Python opencv 读取图像
  11. java JVM调优总结 -Xms -Xmx -Xmn -Xss
  12. 开发微信小程序入门教程,含破解工具
  13. 【springboot进阶】RestTemplate 集成 okhttp3 请求带p12证书
  14. 模板四十天之一 KMP
  15. 【基于TCP 在线电子词典】
  16. stm32 cortex M3 汇编指令集 英文详解
  17. cdoj1338郭大侠与英雄学院
  18. 在右键中添加CMD快速通道
  19. Linux——Linux驱动之Makefile编译总结(编译器路径设置、编译流程分析、编译试验测试)
  20. 儿时便立志在清华读书,参与三国杀发明,被竞赛学子称为「楼教主」,在他身上还有怎样的传奇故事?

热门文章

  1. matlab怎么产生一个随机数,matlab怎么产生随机数
  2. Excel数值函数(3):对“自动筛选”的结果求和、平均值、极值等
  3. 在线K歌又现新模式 音遇APP能否站稳脚跟?
  4. CSDN 去除图片水印
  5. project2016调配资源冲突
  6. 从照片中读取经纬度信息
  7. Personalized Ranking Metric Embedding for Nest New POI Recommendation
  8. void test();
  9. 中亦安图递交注册:拟募资6亿 年营收近12亿
  10. Android 相机教程,Android 相机教程