//最长上升子序列合
//f[i]是第i位的最大上升子序列合,设k为倒数第二位的话
//那f[i]=f[k]+a[i],以此类推
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,res,a[N],f[N];
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
f[i]=a[i];
for(int j=0;j<i;j++)
if(a[i]>a[j]) f[i]=max(f[i],f[j]+a[i]);
}
for(int i=0;i<n;i++) res=max(res,f[i]);
cout<<res;
return 0;
}
//最长不上升子序列(下降)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],q[N],res;
int main()
{
cin>>n;
q[0]=2e9;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
if(q[res]>=a[i]) q[++res]=a[i];
else{
int l=0,r=len;
while(l<=r){
int mid=l+r>>1;
if (q[mid]<a[i]) r=mid-1;
else l=mid+1;
}
q[l]=a[i];
}
}
cout<<res;
return 0;
}
//怪盗基德滑翔翼
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,res,a[N],q[N],len;
int main()
{
cin>>n;
q[0]=-2e9;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
if(q[len]<a[i]) q[++len]=a[i];
else{
int l=0,r=n-1;
while(l<=r){
int mid=l+r>>1;
if(q[mid]>=a[i]) r=mid-1;
else l=mid+1;
}
q[l]=a[i];
}
}
res=len,len=0;
memset(q,0,sizeof q);
q[0]=2e9;
for(int i=n-1;i>=0;i--)
{
if(q[len]<a[i]) q[++len]=a[i];
else{
int l=0,r=n-1;
while(l<=r){
int mid=l+r>>1;
if(q[mid]>=a[i]) r=mid-1;
else l=mid+1;
}
q[l]=a[i];
}
}
cout<<max(res,len)<<endl;
return 0;
}
//登山,合唱队形:https://www.luogu.com.cn/problem/P1091
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int f[N],g[N],n,m,res,a[N],t,q[N];
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
f[i]=1;
for(int j=0;j<i;j++)
if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
}
for(int i=n-1;i>=0;i--)
{
g[i]=1;
for(int j=n-1;j>=i;j--)
if(a[i]>a[j]) g[i]=max(g[i],g[j]+1);
}
for(int i=0;i<n;i++) res=max(res,g[i]+f[i]-1);
cout<<res;//登山
cout<<n-res;//合唱队行
return 0;
}
//友好城市:https://www.luogu.com.cn/problem/P2782
//只需要对y从城市排序,然后求x的最长上升子序列就可以
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int x,n,res,len=0,q[N],f[N];
struct node
{
int x,y;
bool operator<(const node&w)const
{
return y<w.y;
}
}city[N];
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>city[i].x>>city[i].y;
sort(city,city+n);
q[0]=-2e9;
for(int i=0;i<n;i++)
{
if(q[len]<city[i].x) q[++len]=city[i].x;
else{
int l=0,r=len;
while(l<=r){
int mid=l+r>>1;
if(q[mid]>=city[i].x) r=mid-1;
else l=mid+1;
}
q[l]=city[i].x;
}
}
cout<<len;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N],q[N],res;
int main()
{
while(cin>>a[n]) n++;
q[0]=2e9;
for(int i=0;i<n;i++)
{
if(q[res]>=a[i]) q[++res]=a[i];
else{
int l=0,r=res;
while(l<=r){
int mid=l+r>>1;
if(q[mid]<a[i]) r=mid-1;
else l=mid+1;
}
q[l]=a[i];
}
}
cout<<res<<endl;
memset(q,0,sizeof q);
q[0]=-2e9,res=0;
for(int i=0;i<n;i++)
{
if(q[res]<a[i]) q[++res]=a[i];
else{
int l=0,r=res;
while(l<=r){
int mid=l+r>>1;
if(q[mid]>=a[i]) r=mid-1;
else l=mid+1;
}
q[l]=a[i];
}
}
cout<<res<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],res,f[N],ans;
bool vis[N];
void dfs1(int num)
{
if(num==n){
res++;
return;
}
if(vis[num]) dfs1(num+1);
for(int i=num+1;i<n;i++)
if(a[i]>a[num]) vis[i]=true,dfs1(i);
}
void dfs2(int num)
{
if(num==n){
ans++
return;
}
if(vis[num]) dfs2(num+1);
for(int i=num+1;i<n;i++)
if(a[i]<a[num]) vis[i]=true,dfs2(i);
}
int main()
{
while(cin>>n&&n!=0)
{
res=0;
memset(vis,false,sizeof vis);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) if(!vis[i]) dfs1(i);
memset(vis,false,sizeof vis);
for(int i=0;i<n;i++) if(!vis[i]) dfs2(i);
res=min(res,ans);
cout<<res<<endl;
}
return 0;
}
//导弹防御系统:https://www.acwing.com/problem/content/description/189/\
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],q[N],q1[N],res,n;
void dfs(int now,int up,int down)//当前的数,上升序列的个数,下降序列的个数
{
if(up+down>=res) return;//剪枝
if(now==n){
res=up+down;
return;
}
//情况一,上升子序列;
//终于明白q的意义了,q里面代表的不是一个上升子序列,而是某个上升子序列的最大值
//然后利用当前数的大小与某个上升子序列的最大值比,如果大,那就接上去,如果小,那就比下一个,如果都不行,那就新建一个
int len=0;
while(len<up&&a[now]<=q[len]) len++;//q序列是单调递增的,模拟一下发现,如果当前这个数无法加入当前这个上升子序列
//也就是说,我们的q头是上升子序列的最大值,如果当前的数比它小,那么它就无法加入,而len就是新的子序列的第一个元素位置
//这里的while循环可以用二分代替,也就是咱们那个nlogn的时间复杂度算法,所以我们这里用二分!
//就是来找第一个<=q的元素!!
int t=q[len];//为了回溯做准备
q[len]=a[now];//如果能接,那就更新序列的最大值,如果不能,那就这个就是在新的序列中更新最大值
if(len<up) dfs(now+1,up,down);//如果len>=up,说明什么?
//说明len的数都要比当前的数大,那就要开一个新得序列;
//如果len<up,说明当前这个数可以加到某一个序列中去,并且更新这个序列的最大值,就不用新建序列了!!!!
else dfs(now+1,up+1,down);//如果=它,说明这个序列需要更新了,要+1;
q[len]=t;
//情况二,下降子序列;
len=0;
while(len<down&&a[now]>=q1[len]) len++;//与上升子序列顺序相反,思路差不多;
t=q1[len];
q1[len]=a[now];
if(len<down) dfs(now+1,up,down);
else dfs(now+1,up,down+1);
q1[len]=t;
}
int main()
{
while(cin>>n,n){
for(int i=0;i<n;i++) cin>>a[i];
res=n;
dfs(0,0,0);
cout<<res<<endl;
}
return 0;
}
//最长公共上升子序列:http://poj.org/problem?id=2127
//1-1 朴素二维数组做法
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N],f[N][N],res,b[N],n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
f[i][j]=max(f[i][j],1);
for(int k=1;k<j;k++)
if(b[j]>b[k])
f[i][j]=max(f[i][j],f[i][k]+1);
}
}
for(int i=0;i<n;i++) res=max(res,f[n][i]);
cout<<res;
return 0;
}
//1-2 优化算法on2
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N],f[N][N],res,b[N],n,m;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>m;
for(int i=1;i<=m;i++) cin>>b[i];
for(int i=1;i<=n;i++)
{
int maxv=1;
for(int j=1;j<=m;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j]) f[i][j]=max(f[i][j],maxv);
if(a[i]>b[j]) maxv=max(maxv,f[i][j]+1);
}
}
for(int i=1;i<=n;i++) res=max(res,f[n][i]);
cout<<res;
return 0;
}
//1-3 容易理解的优化算法
#include<bits/stdc++.h>
using namespace std;
const int N=2020;
int n,m,res,f[N][N],a[N],b[N];
int g[N][N];//g[n][n]表示的是g数组,在满足a[i]>b[j]的情况下,f[i][j]+1的最大值
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++)
{
g[i][0]=1;//从i开始,b数组的第0位设为1
for(int j=1;j<=n;j++)//枚举b数组
{
f[i][j]=f[i-1][j];
if(a[i]==b[j]) f[i][j]=max(f[i][j],g[i][j-1]);
g[i][j]=g[i][j-1];//目前肯定是上一位的最大值嘛
if(a[i]>b[j]) g[i][j]=max(g[i][j],f[i-1][j]+1);//如果符合,更新
}
}
for(int i=1;i<=n;i++) res=max(res,f[n][i]);
cout<<res;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)