题解 HDU - 3530 Subsequence
题目描述
给出一个长度为
令
方法一
因为考试的时候没有马上想到正解,所以随便就打上了一个 ST 表,
于是我们可以枚举左端点,然后,我们在
于是我们就可以马上想到我们可以用二分来计算每个
Code。
#include <bits/stdc++.h> //#define int long long using namespace std; const int N = 1e5+5; int n, m,K; int a[N]; int st[2][N][20]; int d[N]; inline int query(int l,int r,int opt) { int len=r-l+1; if(opt) return max(st[1][l][d[len]],st[1][r-(1<<d[len])+1][d[len]]); return min(st[0][l][d[len]],st[0][r-(1<<d[len])+1][d[len]]); } inline int check(int l,int r) { return query(l,r,1)-query(l,r,0); } signed main() { for(int i=2; i<N; ++i) d[i]=d[i/2]+1; while(cin>>n>>m>>K) { for(int i=1; i<=n; ++i) cin>>a[i],st[0][i][0]=st[1][i][0]=a[i]; for(int i=1; i<20; ++i) { for(int j=1; j+(1<<i)-1<=n; ++j) { st[1][j][i]=max(st[1][j][i-1],st[1][j+(1<<i-1)][i-1]); st[0][j][i]=min(st[0][j][i-1],st[0][j+(1<<i-1)][i-1]); } } int ans=0; for(int i=1; i<=n; ++i) { int l=i,r=n,res=-1; while(l<=r) { int mid=l+r>>1; int dt=check(i,mid); if(dt<=K) { if(m<=dt) res=mid; l=mid+1; } else r=mid-1; } if(res!=-1) ans=max(ans,res-i+1); } cout<<ans<<endl; } return 0; }
方法二
与方法一相同的,依旧是基于 ST 表,但是,当相同的
Code
#include <bits/stdc++.h> //#define int long long using namespace std; const int N = 1e5+5; int n, m,K; int a[N]; int st[2][N][20]; int d[N]; inline int query(int l,int r,int opt) { int len=r-l+1; if(opt) return max(st[1][l][d[len]],st[1][r-(1<<d[len])+1][d[len]]); return min(st[0][l][d[len]],st[0][r-(1<<d[len])+1][d[len]]); } inline int check(int l,int r) { return query(l,r,1)-query(l,r,0); } signed main() { for(int i=2; i<N; ++i) d[i]=d[i/2]+1; while(cin>>n>>m>>K) { for(int i=1; i<=n; ++i) cin>>a[i],st[0][i][0]=st[1][i][0]=a[i]; for(int i=1; i<20; ++i) { for(int j=1; j+(1<<i)-1<=n; ++j) { st[1][j][i]=max(st[1][j][i-1],st[1][j+(1<<i-1)][i-1]); st[0][j][i]=min(st[0][j][i-1],st[0][j+(1<<i-1)][i-1]); } } int ans=0; int r=1; for(int i=1; i<=n; ++i) { while(r<=n) { int dt=check(i,r); if(dt<=K) ++r; else break; } if(m<=check(i,r-1)) ans=max(ans,r-i); } cout<<ans<<endl; } return 0; }
方法三、四
其实也不能算新方法,就是用线段树来替换我们的 ST 表,比较懒就不打了。
方法五
承接我们方法二的双指针,我们的难点其实只是在与删除,在加点时我们并没有难度,我们可以用单调队列来维护我们的删除操作。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现