【HDU4521】 dp思想+线段树操作
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4521
题目大意:有n个数,求间距大于d的最长递增子序列。
解题思路:扎眼一看,不是简单的dp嘛,再眨眼一看,n最大为10^5,蛋碎一地呀。
这题不仅要线段树功底好,还要有比较强的dp思想,从第d+1个位置开始更新,每个节点的sum值保存的是从第1个数到当前数的最长符合要求的子序列,查询的时候只需查询线段树中值在其左边的最大的sum[u](最长符合要求序列)。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 using namespace std; 7 8 #define lz 2*u,l,mid 9 #define rz 2*u+1,mid+1,r 10 const int maxn=110000; 11 int sum[2*maxn], dp[maxn+5], a[maxn+5]; 12 13 void Update(int u, int l, int r, int p, int c) 14 { 15 sum[u]=max(sum[u],c); 16 if(l==r)return ; 17 int mid=(l+r)>>1; 18 if(p<=mid) Update(lz,p,c); 19 else Update(rz,p,c); 20 } 21 22 int Query(int u, int l, int r, int tl, int tr) 23 { 24 if(tl>tr) return 0; 25 if(tl<=l&&r<=tr) return sum[u]; 26 int mid=(l+r)>>1; 27 if(tr<=mid) return Query(lz,tl,tr); 28 else if(tl>mid) return Query(rz,tl,tr); 29 else 30 { 31 int t1=Query(lz,tl,mid); 32 int t2=Query(rz,mid+1,tr); 33 return max(t1,t2); 34 } 35 } 36 37 int main() 38 { 39 int n, d; 40 while(scanf("%d%d",&n,&d)!=EOF) 41 { 42 memset(sum,0,sizeof(sum)); 43 for(int i=1; i<=n; i++) 44 scanf("%d",a+i); 45 int maxx=0; 46 for(int i=1; i<=n; i++) 47 { 48 if(i>d+1) Update(1,1,maxn,a[i-d-1]+1,dp[i-d-1]); ///注意a[i-d-1]要加1 49 dp[i]=Query(1,1,maxn,1,a[i])+1; 50 maxx=max(dp[i],maxx); 51 } 52 printf("%d\n",maxx); 53 } 54 return 0; 55 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】