B3637 最长上升子序列
1.如图,以最后的元素4为例,大于a[1]则可接更新ans为1,又大于a[2]则可接更新ans为2,以此类推,最后大于a[5]可接则更新ans为3,最后加上自身为4
n | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
an | 1 | 2 | 4 | 1 | 3 | 4 |
f(n) | 1 | 2 | 3 | 1 | 3 | 4 |
#include <bits/stdc++.h>
using namespace std;
int a[5000], ans[5000], n;
int main(){
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
}
ans[0] = 1;
for(int i = 1; i < n; i++){
int maxx = 0;
for(int j = 0; j < i; j++){ //遍历自身前面所有数
if(a[j] < a[i]) maxx = max(maxx, ans[j]); //,若大于a[j]说明能接在后面组成新的子序列,比较最长子序列数,更新
}
ans[i] = maxx + 1; //加上自身的数字
}
sort(ans, ans + n); //升序排列
cout << ans[n - 1];
return 0;
}
P1115 最大子段和
1.思路即为实时比较最大值与当前累加值
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int main()
{
int n;
int a[maxn];
int sum, ans;
cin >> n;
sum = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (!i)
{
ans = a[0]; //初始化,将a[0]赋给ans
}
sum += a[i]; // 累加a[i]
ans = max(ans, sum); //实时比较最大值与当前累加值sum
if (sum < 0) //如sum小于0,说明a[i]没有贡献,即加了负数还变小了
{
sum = 0; //则不如清零,从下一个数重新开始累加
}
}
cout << ans << endl;
return 0;
}
P8707 [蓝桥杯 2020 省 AB1] 走方格
1满足递归公式a[i][j]=a[i-1][j]+a[i][j-1]
#include <bits/stdc++.h>
using namespace std;
int n,m,a[100][100];
int main(){
cin>>n>>m;
a[1][1]=1;
for(int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
if((i%2==1||j%2==1) && (i!=1|| j!=1) ){ //坐标不都为偶数且不在a[1][1]原点处
a[i][j]=a[i-1][j]+a[i][j-1];
}
}
}
cout<<a[n][m];
return 0;
}
P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles
1.要求求和最大的一条分支,可以从倒着看,最下面大数加入上一行,以此类推
#include <bits/stdc++.h>
using namespace std;
int n,a[1010][1010];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
for (int i=n-1;i>0;i--){ //从倒数第二行开始往上运算
for(int j=1;j<=i;j++){
a[i][j]+=max(a[i+1][j],a[i+1][j+1]); //比较左右分支大小,加上大者更新
}
}
cout<<a[1][1];
return 0;
}
P1020 [NOIP1999 普及组] 导弹拦截
1.循环时间复杂为n,二分时间复杂度为logn,总时间复杂度为O(nlogn)
2.f[i]表示第i套拦截系统最低拦截高度
#include <bits/stdc++.h>
using namespace std;
int n,a[100005],dp[100005],ans=1,p;
int f[100005],cnt=1;
int main(){
while(cin>>a[++n]); n--;
dp[1]=a[1];f[1]=a[1];
for (int i=2;i<=n;i++){
if(dp[ans]>=a[i]) dp[++ans]=a[i]; //求最长降序子数列长度ans
else { //a[i]比末尾小直接接入,长度ans加一
p=upper_bound(dp+1,dp+1+ans,a[i],greater<int>())-dp; //替换
dp[p]=a[i];
}
if(f[cnt]<a[i]) f[++cnt]=a[i]; //求降序子数列个数cnt
else{ //如大于子数列的头,则需要新开一个子数列,cnt加一
p=lower_bound(f+1,f+1+cnt,a[i])-f;
f[p]=a[i];
}
}
cout<<ans<<endl<<cnt<<endl;
return 0;
}