poj-2823 -- Sliding Window 区间最大值最小值 RMQ 与线段树

题意:一个有n个元素的数组num[],求所有num[i]~num[i+k]的最小值和最大值。

RMQ 算法小心空间,很容易被卡到

可以用线段树做,每个结点保存该线段的最大/小值...然后简单查询最大最小值即可

RMQ:

View Code
 1 //Accepted    8008K    6110MS    C++    1577B 超卡空间
 2 #include <cstdio>
 3 #include <string>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 const int MAX = 1000001;
 8 int n,q;
 9 int st[MAX];
10 int val[MAX];
11 inline int minn(int a,int b){ return a>b?b:a; }
12 inline int maxx(int a,int b){ return a>b?a:b; }
13 void make_st_max()
14 {
15     int i,j,k;
16     for( i=1; i<=n; i++)
17           st[i] = val[i];    //实质是: dp[i][0]
18     k = log(double(q)) / log(2.0);
19     for( j=1; j<=k; j++)
20         for( i=1; i+(1<<j)-1 <= n; i++)
21                             st[i] = maxx( st[i] , st[i+(1<<(j-1))]);  
22 //实质是: max( dp[i][j-1] , dp[i+(1<<(j-1))][j-1]); 这里,因为有用到dp[i][log(double(K)) / log(2.0)]的值,所以用滚动数组就可以了
23 }
24 void make_st_min()
25 {
26     int i,j,k;
27     for( i=1; i<=n; i++)
28           st[i] = val[i];    //实质是: dp[i][0]
29     k = log(double(q)) / log(2.0);
30     for( j=1; j<=k; j++)
31         for( i=1; i+(1<<j)-1 <= n; i++)
32                             st[i] = minn( st[i] , st[i+(1<<(j-1))]);  
33         //实质是: max( dp[i][j-1] , dp[i+(1<<(j-1))][j-1]); 这里,因为有用到dp[i][log(double(K)) / log(2.0)]的值,所以用滚动数组就可以了
34 }
35 
36 int rmq(int a,int b,int flag)
37 {    
38     int k;
39     k=floor(log((double)(b-a+1))/log(2.0));
40     if(flag > 0)
41     {
42         return  maxx(st[a], st[b-(1<<k)+1]);
43     }
44     else
45     {
46         return minn(st[a], st[b-(1<<k)+1]);
47     }
48 }
49 
50 int main(void)
51 {
52     int i;
53     while(scanf("%d%d",&n,&q)!=EOF)
54     {
55         for(i=1;i<=n;i++)
56         {
57             scanf("%d",&val[i]);
58         }
59         make_st_min();
60         for(i=1;i<=n-q+1;i++)
61         {
62             printf("%d ",rmq(i,i+q-1,-1));
63         }
64         printf("\n");
65         make_st_max();
66         for(i=1;i<=n-q+1;i++)
67         {
68             printf("%d ",rmq(i,i+q-1,1));
69         }
70         printf("\n");
71     }
72     return 0;
73 }

线段树:

View Code
 1 //Accepted    16596K    9204MS    C++    1487B
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define  inf 0x7fffffff
 5 #define lson l , m , rt << 1
 6 #define rson m + 1 , r , rt << 1 | 1
 7 const int maxn = 1000001;
 8 
 9 int st_min[maxn<<2],st_max[maxn<<2];
10 
11 inline int minn(int a,int b) { return a>b?b:a; }
12 inline int maxx(int a,int b) { return a>b?a:b; }
13 void PushUP(int rt)
14 {
15     st_min[rt] = minn(st_min[rt<<1],st_min[rt<<1|1]);
16     st_max[rt] = maxx(st_max[rt<<1],st_max[rt<<1|1]);
17 }
18 void build(int l,int r,int rt) {
19     if (l == r)
20     {
21         scanf("%d",&st_min[rt]);
22         st_max[rt] = st_min[rt];
23         return ;
24     }
25     int m = (l + r) >> 1;
26     build(lson);
27     build(rson);
28     PushUP(rt);
29 }
30 
31 int query_min(int L,int R,int l,int r,int rt) 
32 {
33     if (L <= l && r <= R) {
34         return st_min[rt];
35     }
36     int m = (l + r) >> 1;
37     int ret1 = inf,ret2 = inf;
38     if (L <= m) ret1 = query_min(L , R , lson);
39     if (R > m) ret2 = query_min(L , R , rson);
40     return minn(ret1,ret2);
41 }
42 int query_max(int L,int R,int l,int r,int rt) 
43 {
44     if (L <= l && r <= R) {
45         return st_max[rt];
46     }
47     int m = (l + r) >> 1;
48     int ret1 = -inf,ret2 = -inf;
49     if (L <= m) ret1 = query_max(L , R , lson);
50     if (R > m) ret2 = query_max(L , R , rson);
51     return maxx(ret1,ret2);
52 }
53 
54 int main(void)
55 {
56     int n,m,i;
57     while(scanf("%d%d",&n,&m)!=EOF)
58     {
59         build(1 , n , 1);
60         for(i=1;i<=n-m+1;i++)
61         {
62             printf("%d ",query_min(i,i+m-1,1,n,1));
63         }
64         printf("\n");
65         for(i=1;i<=n-m+1;i++)
66         {
67             printf("%d ",query_max(i,i+m-1,1,n,1));
68         }
69         printf("\n");
70     }
71     return 0;
72 }

 

 

posted @ 2012-08-24 19:23  Wheat″  阅读(756)  评论(0编辑  收藏  举报