标签:style blog color io os for 数据 sp div
题意:求最长上升序列的长度(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_JUDGE 52 freopen("in.txt","r",stdin); 53 #endif 54 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开始的所以加2 63 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-小明系列问题——小明序列(线段树区间求最值)
标签:style blog color io os for 数据 sp div
原文地址:http://www.cnblogs.com/oneshot/p/3995640.html