CSU1553 Good subsequence —— 二分 + RMQ/线段树

题目链接: http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1553


 

Description

Give you a sequence of n numbers, and a number k you should find the max length of Good subsequence. Good subsequence is a continuous subsequence of the given sequence and its maximum value - minimum value<=k. For example n=5, k=2, the sequence ={5, 4, 2, 3, 1}. The answer is 3, the good subsequence are {4, 2, 3} or {2, 3, 1}.

 

Input

There are several test cases.
Each test case contains two line. the first line are two numbers indicates n and k (1<=n<=10,000, 1<=k<=1,000,000,000). The second line give the sequence of n numbers a[i] (1<=i<=n, 1<=a[i]<=1,000,000,000). 
The input will finish with the end of file.

 

Output

For each the case, output one integer indicates the answer.

 

Sample Input

5 2
5 4 2 3 1
1 1
1

Sample Output

3
1

 

 


题解:

之前学了RMQ,线段树, 树状数组,但是一直不知道他们在哪里能派上用场。通过这题,终于找到他们的用武之地了:区间查询最大最小值。

解决了查询区间最大最小值的问题,剩下的就是二分了。这里是二分长度。



RMQ:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 #define eps 0.0000001
18 #define LNF (1<<60)
19 typedef long long LL;
20 const int inf = 0x3f3f3f3f;
21 const int maxn = 10000+10;
22 const int mod = 1e9+7;
23 
24 LL st_max[maxn][16], st_min[maxn][16];
25 LL a[maxn];
26 
27 void RMQ_init(int n)
28 {
29     for(int i = 0; i<n; i++)
30     {
31         st_min[i][0] = a[i];
32         st_max[i][0] = a[i];
33     }
34 
35     for(int j = 1; (1<<j)<=n; j++)//枚举长度
36     for(int i = 0; i+(1<<j)-1<n; i++)//枚举起点
37     {
38         st_min[i][j] = min(st_min[i][j-1],st_min[i+(1<<(j-1))][j-1]);
39         st_max[i][j] = max(st_max[i][j-1],st_max[i+(1<<(j-1))][j-1]);
40     }
41 }
42 
43 LL RMQ(int l, int r)//查询
44 {
45     int k = 0;
46     while((1<<(k+1))<=r-l+1)
47         k++;
48     return max(st_max[l][k],st_max[r-(1<<k)+1][k]) - min(st_min[l][k],st_min[r-(1<<k)+1][k]);
49 }
50 
51 int test(int len, int n, int k)
52 {
53     for(int i = len-1; i<n; i++)
54         if(RMQ(i-len+1, i)<=1LL*k)
55             return 1;
56 
57     return 0;
58 }
59 
60 int main()
61 {
62 #ifdef LOCAL
63     freopen("input.txt", "r", stdin);
64 //      freopen("output.txt", "w", stdout);
65 #endif // LOCAL
66 
67     int n, k;
68     while(~scanf("%d%d", &n, &k))
69     {
70         for(int i=0;i<n;i++)
71             scanf("%lld", &a[i]);
72 
73         ms(st_max, 0);
74         ms(st_min, 0);
75         RMQ_init(n);
76 
77         int l = 1, r = n;
78         while(l<=r)
79         {
80             int mid = (l+r)/2;
81             if(test(mid, n, k))
82                 l = mid+1;
83             else
84                 r = mid-1;
85         }
86         printf("%d\n", r);
87     }
88     return 0;
89 }
View Code


线段树:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 #define eps 0.0000001
18 #define LNF 1000000000000
19 typedef long long LL;
20 const int inf = 0x3f3f3f3f;
21 const int maxn = 10000+10;
22 const int mod = 1e9+7;
23 
24 LL st_max[4*maxn], st_min[4*maxn];
25 LL a[maxn];
26 
27 void build(int rt, int l, int r)
28 {
29     if(l==r)
30     {
31         st_max[rt] = a[r];
32         st_min[rt] = a[r];
33         return;
34     }
35 
36     int mid = (l+r)>>1;
37     build(rt*2,l,mid);
38     build(rt*2+1,mid+1,r);
39     st_max[rt] = max(st_max[rt*2], st_max[rt*2+1]);
40     st_min[rt] = min(st_min[rt*2], st_min[rt*2+1]);
41 }
42 
43 //由于最大最小值都要查询,而return只能返回一个,所以用ma和mi记录最小值
44 LL query(int rt, int l, int r, int x, int y, LL &ma, LL &mi)
45 {
46     if(x<=l && y>=r)
47     {
48         ma = max(ma,st_max[rt]);
49         mi = min(mi,st_min[rt]);
50         return ma - mi;
51     }
52 
53     int mid = (l+r)>>1;
54     if(y<=mid) query(rt*2,l,mid,x,y,ma,mi);
55     else if(x>=mid+1) query(rt*2+1,mid+1,r,x,y,ma,mi);
56     else query(rt*2,l,mid,x,mid,ma,mi),query(rt*2+1,mid+1,r,mid+1,y,ma,mi);
57 
58     return ma - mi;
59 }
60 
61 int test(int len, int n, int k)
62 {
63     for(int i = len-1; i<n; i++)
64     {
65         LL ma = -LNF, mi = LNF;
66         if(query(1,0,n-1, i-len+1, i, ma,mi)<=1LL*k)
67             return 1;
68     }
69     return 0;
70 }
71 
72 int main()
73 {
74 #ifdef LOCAL
75     freopen("input.txt", "r", stdin);
76 //      freopen("output.txt", "w", stdout);
77 #endif // LOCAL
78 
79     int n, k;
80     while(scanf("%d%d", &n, &k)!=EOF)
81     {
82         for(int i=0;i<n;i++)
83             scanf("%lld", &a[i]);
84 
85         build(1,0,n-1);
86 
87         int l = 1, r = n;
88         while(l<=r)
89         {
90             int mid = (l+r)/2;
91             if(test(mid, n,k))
92                 l = mid+1;
93             else
94                 r = mid-1;
95         }
96         printf("%d\n", r);
97     }
98     return 0;
99 }
View Code

 

posted on 2017-04-20 23:23  h_z_cong  阅读(213)  评论(0编辑  收藏  举报

导航