首页 > 代码库 > hdu4521-小明系列问题——小明序列(线段树区间求最值)
hdu4521-小明系列问题——小明序列(线段树区间求最值)
题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE。线段树搞之就可以了,或者优化后的nlogn的dp。
代码为 线段树解法。
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cctype> 8 #include <cstdio> 9 #include <string>10 #include <vector>11 #include <cstdlib>12 #include <cstring>13 #include <iostream>14 #include <algorithm>15 using namespace std;16 typedef unsigned long long ull;17 typedef long long ll;18 const int inf = 0x3f3f3f3f;19 const double eps = 1e-8;20 const int maxn = 1e5+10;21 int dp[maxn],seg[maxn<<2]; //线段树区间求最值22 int a[maxn];23 void update(int l,int r,int pos,int x,int val)24 {25 if (l == r)26 {27 seg[pos] = val;28 return ;29 }30 int mid = (l + r) >> 1;31 if (x <= mid)32 update(l,mid,pos<<1,x,val);33 if (x > mid)34 update(mid+1,r,pos<<1|1,x,val);35 seg[pos] = max(seg[pos<<1],seg[pos<<1|1]);36 }37 int query(int l,int r,int pos,int x,int y)38 {39 if (x <= l && y >= r)40 return seg[pos];41 int mid = (l + r) >> 1;42 int ans1 = 0,ans2 = 0;43 if (x <= mid)44 ans1 = query(l,mid,pos<<1,x,y);45 if (y > mid)46 ans2 = query(mid+1,r,pos<<1|1,x,y);47 return max(ans1,ans2);48 }49 int main(void)50 {51 #ifndef ONLINE_JUDGE52 freopen("in.txt","r",stdin);53 #endif54 int n,d;55 while (~scanf ("%d%d",&n,&d))56 {57 memset(seg,0,sizeof(seg));58 int len = 0;59 for (int i = 0; i < n; i++)60 {61 scanf ("%d",a+i);62 a[i] += 2; //因为a[i]可能为0,而我的线段树是从1开始的所以加263 len = max(len,a[i]);64 }65 int ans = 1;66 for (int i = 0; i < n; i++)67 {68 dp[i] = query(1,len,1,1,a[i]-1) + 1; //不能等于,所以减1,dp[i]表示以a[i]结尾的最长不降序列长度,69 if (i >= d) //延迟更新,这是这道题的关键,70 update(1,len,1,a[i-d],dp[i-d]);71 ans = max(dp[i],ans);72 }73 printf("%d\n",ans);74 }75 return 0;76 }
hdu4521-小明系列问题——小明序列(线段树区间求最值)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。