看文先三连,养成好习惯~看文先三连,养成好习惯~看文先三连,养成好习惯~
目录
知识点:
求最大连续子序列:
分解子问题:
1.按区间长度划分
2.按区间起点划分
3.按区间终点划分
状态:
状态转移方程:
最长上升子序列:(LIS)
状态转移方程:
优化:
~题题题题~
最大子段和
题目描述
输入描述
输出描述
样例输入
样例输出
代码
最长上升子序列
题目描述
输入描述
输出描述
样例输入
样例输出
提示
状态转移方程:
代码
拦截导弹
题目描述
输入描述
输出描述
样例输入
样例输出
代码
最长上升子序列2
题目描述
输入描述
输出描述
样例输入
样例输出
提示
代码
知识点:
求最大连续子序列:
分解子问题:
1.按区间长度划分
不符合最优子结构
(最优子结构请看D4--数字三角形-CSDN博客)
2.按区间起点划分
3.按区间终点划分
2.3.差不多
下标 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
数组a | 1 | 2 | -5 | 11 | 3 |
求和sum | 1 | 3 | -2 | 11 | 14 |
状态:
sum[i]记录连续子序列最后为a[i]时的最大和
状态转移方程:
sum[i]=max(sum[i-1],0)+a[i];
最长上升子序列:(LIS)
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
num[i] | 3 | 1 | 2 | 6 | 4 | 5 | 10 | 7 |
len[i]以num[i]结尾的最长子序列长度 | 1 | 1 | 2 | 3 | 3 | 4 | 5 | 5 |
状态转移方程:
len[i]=max(len[j])+1; 范围&条件:1<=j<i,num[j]<=num[i]
优化:
比较顺序
原来:按下标遍历
现在:优先找最长的—NO:从头开始遍历(二分法查找位置)
—YES:不需要遍历其他的
~题题题题~
最大子段和
题目描述
小可喜欢思考人生的意义,她发现每个人的一生不可能一帆风顺,或多或少总要经过坎坷挫折的考验。于是她将人的一生的每个关键时间点以数值表示,快乐越高,分值越高,痛苦值越高,分值越低甚至会成为负数。进一步研究,她又发现人的记忆总是会记住那些快乐的时光,而淡忘痛苦的时光。于是小可想统计出某个人连续最大的一段时光总和是多少。
(一堆废话!!!)
即给定K个整数的序列{N1, N2, N2,……, NK},其任意连续子序列可表示为{Ni, Ni+1,……, Nj},其中1≤i≤j≤K。
最大连续子序列是所有连续子序列中元素和最大的一个,例如,给定序列{-2, 11,-4, 13,-5,-2},其最大连续子序列为{11,-4, 13},最大和为20。
输入描述
第一行是一个正整数N<=100000,表示了序列的长度。
第二行包含N个绝对值不大于10000的整数,描述了这段序列。
输出描述
一个整数,为最大的子段和是多少。子段的最小长度为1。
样例输入
7 2 -4 3 -1 2 -4 3
样例输出
4
代码
#include<iostream>
using namespace std;
int n,a[100005],sum[100005];
int maxx=-0x3f3f3f3f;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
sum[i]=max(sum[i-1],0)+a[i];
}
int maxx=0;
for(int i=1;i<=n;i++){
maxx=max(maxx,sum[i]);
}
cout<<maxx;
return 0;
}
最长上升子序列
题目描述
一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入描述
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
输出描述
最长上升子序列的长度。
样例输入
7 1 7 3 5 9 4 8
样例输出
4
提示
另一组测试数据
输入
43
486 341 527 189 740 490 388 989 489 711 174 305 844 971 492 998 954 832 442 424 619 906 154 293 395 439 735 738 915 453 748 786 550 871 932 693 326 53 904 732 835 354 364
输出
11
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
num[i] | 3 | 1 | 2 | 6 | 4 | 5 | 10 | 7 |
len[i]以num[i]结尾的最长子序列长度 | 1 | 1 | 2 | 3 | 3 | 4 | 5 | 5 |
状态转移方程:
len[i]=max(len[j])+1; 条件:1<=j<i,num[j]<=num[i]
代码
#include<iostream>
using namespace std;
int n,a[1005],sum[1005];
int maxx=-0x3f3f3f3f;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
int t=0;
for(int j=1;j<=i;j++){
if(a[i]>a[j]){
t=max(t,sum[j]);
}
}
sum[i]=t+1;
}
int maxx=0;
for(int i=1;i<=n;i++){
maxx=max(maxx,sum[i]);
}
cout<<maxx;
return 0;
}
拦截导弹
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入描述
输入导弹依次飞来的高度。
输出描述
第一行:最多能拦截的导弹数;
第二行:要拦截所有导弹最少要配备的系统数。
样例输入
389 207 155 300 299 170 158 65
样例输出
6 2
代码
#include<iostream>
using namespace std;
int a[1005],sum[1005],b[1005];
int k=1,ans=1,f=0;
int maxx=0;
int main(){
while(cin>>a[k]){
k++;
}
k--;
for(int i=1;i<=k;i++){
int t=0;
for(int j=1;j<=i;j++){
if(a[i]<=a[j]){
t=max(t,sum[j]);
}
}
sum[i]=t+1;
}
for(int i=1;i<=k;i++){
maxx=max(maxx,sum[i]);
}
cout<<maxx<<"\n";
b[1]=a[1];
for(int i=2;i<=k;i++){
f=0;
for(int j=1;j<=ans;j++){
if(b[j]>=a[i]){
b[j]=a[i];
f=1;
break;
}
}
if(f==0){
b[++ans]=a[i];
}
}
cout<<ans;
return 0;
}
最长上升子序列2
题目描述
给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。
输入描述
第一行包含整数 N。
第二行包含 N 个整数,表示完整序列。
输出描述
输出一个整数,表示最大长度。
样例输入
7 3 1 2 1 8 5 6
样例输出
4
提示
N<=1e5
−10^9≤数列中的数≤10^9
代码
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
int a[100005],le[100005],n,ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ans=1;
le[ans]=a[1];
for(int i=2;i<=n;i++){
if(a[i]>le[ans]){
ans++;
le[ans]=a[i];
}
else{
int l=1,r=ans;
while(l<r){
int mid=(l+r)/2;
if(le[mid]>=a[i]){
r=mid;
}
else{
l=mid+1;
}
}
le[l]=a[i];
}
}
cout<<ans;
return 0;
}
创作不易,点个关注吧~创作不易,点个关注吧~创作不易,点个关注吧~