首页 > 其他分享 >洛谷 P1020 导弹拦截(递增子串 DP )

洛谷 P1020 导弹拦截(递增子串 DP )

时间:2022-12-12 19:38:39浏览次数:65  
标签:子串 洛谷 int poi pos P1020 单调 lis DP


题目大意:

有一个数列,我们要获取一组子串,这个子串必须单调不增。

问:

(1)最长 我们可以获取多长的这种子串

(2)这个数列中最多有多少种 这种子串

解题思路:

其中问题一是很典型的DP问题,最大不增子串。关键是第二问,我们要把第二问转一转思路,一种想法是贪心:我们每次都从这个串抽出单调不增子串,看能抽取多少次,但是假如这样抽取的话,可以试一下这个样例:

1000 1005 999 998 1004

第二问:输出2是对的 ,分别是 1000 999 998,1005 1004这两个子串。

假如按照贪心抽取的话,结果会是1005 999 998 ,1000,1004这三个子串。原因在于第一个子串的第一个数字取到了1005.

第二种想法:找单调递增子串

这种想法可行是因为,在这个单调递增子串中不存在 单调不增子串,所以这个单调递增子串每个元素都是 所有单调不增子串的首个元素!而且已经是最优,不存在更多的单调不增子串。

关于这种子串应该怎么找。

我们以单调递增子串为例。本质上,我们最后必须通过一个链表输出,所以我们要维护一个链表。另外,我们还要维护一个序列,这个序列有个特点:单调递增。大概流程:

arr 是数列的元素
L=[]
for i in arr:
pos=lower_bound(L,L+lis,i) 找出在L中大于等于i的第一个数字的下标
注意在这里,假如我们要找单调不减子串,那么我们必须找到的是 大于等于i的这个数字的下一个下标
...
L[pos]=i 更新L,重要!
L_id[pos]=i
P[i]=pos==0?-1:L_id[pos-1] 更新P,重要!
...

其中比较重要的是理解为什么链表要这样指,其实这是一种有点类似于贪心的做法,我们指向的是已知的最邻近的比当前小的元素。

#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e5+10;
int L[MAXN];
int Arr[MAXN];
int mybsearch(int l,int r,int val){
while(l<r){
int m=l+(r-l)/2;
if(L[m]<val)r=m;
else if(L[m]>=val)l=m+1;
}
assert(l==r);
return l;
}
int main(){
int n=0;
while(cin>>Arr[n]){
n++;
}
int lis;int lis_end;
int L_id[MAXN];
int P[MAXN];
int finans=0;
lis=0;
L[0]=-1;
for(int i=0;i<n;i++){
int pos=mybsearch(0,lis,Arr[i]);
L[pos]=Arr[i];
L_id[pos]=i;
P[i]=pos!=0?L_id[pos-1]:-1;
if(pos+1>lis){
lis+=1;
lis_end=i;
}
}
for(int poi=lis_end;poi!=-1;poi=P[poi]){
finans++;
}
int LIS=0;
lis=0;
for(int i=0;i<n;i++){
int pos=lower_bound(L,L+lis,Arr[i])-L;
L[pos]=Arr[i];
L_id[pos]=i;
P[i]=pos!=0?L_id[pos-1]:-1;
if(pos+1>lis){
lis=pos+1;
lis_end=i;
}
}
for(int poi=lis_end;poi!=-1;poi=P[poi]){
LIS++;
}
cout<<finans<<endl;
cout<<LIS<<endl;
return 0;
}

 

标签:子串,洛谷,int,poi,pos,P1020,单调,lis,DP
From: https://blog.51cto.com/u_15910522/5931526

相关文章

  • 洛谷 P1087 FBI树
    题目大意:已知一棵树由字符串组成,规定:若节点全1把这节点称为I节点。若节点全0把节点称为B节点。若节点含0同时含1把节点称为F节点。现在有一个字符串N长,左子树是前一半字......
  • 洛谷 P1088 火星人(乱搞)
    题目大意:已知有一串数字,问在原来的数字串的字典序加m后,应该输出多少解题思路:最简便的做法是用next_permutation,这个生成的全排列可以按照字典序递增,这里我用的是搜索的方法......
  • 洛谷 P1113 杂务(拓扑排序,递归)
    题目大意:有一个有向无圈图,每个节点看作一个任务,一个任务需要完成必须先完成父亲节点的任务,每个任务都有耗时。假设现在所有不相关任务都可以并行执行,问最短多少时间可以把所......
  • 洛谷 P1996 约瑟夫问题
    问题简介:小朋友围城一圈,从1号开始报数,报到M的那位同学出局,然后下一位同学报1,循环上述过程直到所有同学出局。输出依次出局的小朋友的号码解题思路:没什么好说的,就是模拟,出局......
  • codeforces 594 div2 Ivan the Fool and the Probability Theory (DP 推公式)
    题目大意:现在有n*m个格子。然后我们可以对这些格子染上黑色或者白色。规定每个格子最多允许相邻1个与它同样颜色的格子,问你我们有多少中不同的染色方案。解题思路:首先考虑1*......
  • 洛谷 P1233 木棍加工(贪心,递增子串DP)
    题目大意:有矩形A1,A2......An.每个矩形有长宽w,h。现在已知cost:(1)若矩形a的w,h小于矩形b的w,h,那么没有cost(2)其它情况cost+1.现在已知矩形A1,A2...,问怎么得到最少cost.解题思......
  • 拼多多 2020校招 多多的电子字典(字典树前缀搜索,DP)
    多多鸡打算造一本自己的电子字典,里面的所有单词都只由a和b组成。每个单词的组成里a的数量不能超过N个且b的数量不能超过M个。多多鸡的幸运数字是K,它打算把所有满足条件的......
  • leetcode 139. 单词拆分(BFS 或者 DP)
    题目大意:给定一个非空字符串s和一个包含非空单词列表的字典wordDict,判定 s是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。......
  • 洛谷 P1057 传球游戏(背包DP)
    题目大意:有n个人围成一圈,每个人可以把手上的球传给左边或者右边,现在小明开始传球,问m次后,把球传回给自己的次数。解题思路:考虑DP,使用带记忆的DP, 首先我们的状态可以设为[还......
  • 7天7个云实验(阿里云版) | Day 1-基于ECS部署WordPress
    在前面我们介绍过云计算的7个核心产品/服务,而只是看文章、看视频学习效果有限,而通过动手实验的方式来操作一遍,能够更容易、更扎实的掌握云服务。本期《7天7个云实验》将会介......