poj-2823 -- Sliding Window 区间最大值最小值 RMQ 与线段树
题意:一个有n个元素的数组num[],求所有num[i]~num[i+k]的最小值和最大值。
RMQ 算法小心空间,很容易被卡到
可以用线段树做,每个结点保存该线段的最大/小值...然后简单查询最大最小值即可
RMQ:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
线段树:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }