来源:http://poj.org/problem?id=2823
题意:给一些数,每次可以看k个数。从左向右顺序每次k个数,问每次的最大值 和最小值 是多少。
思路:RMQ的问题,用线段树松松水过。
代码:
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int N = 1000010;
struct tree{
int lp,rp,minvalue,maxvalue;
int getmid(){
return (lp + rp) / 2;
}
}tt[N * 4];
struct ans{
int minans,maxans;
}aa[N];
int num[N];
int min(int a,int b){
return a < b ? a : b;
}
int max(int a,int b){
return a > b ? a : b;
}
void built_tree(int lp,int rp,int pos){
tt[pos].lp = lp;
tt[pos].rp = rp;
int mid = tt[pos].getmid();
if(lp == rp){
tt[pos].minvalue = tt[pos].maxvalue = num[lp];
return;
}
built_tree(lp,mid,pos*2);
built_tree(mid+1,rp,pos*2+1);
tt[pos].minvalue = min(tt[pos*2].minvalue,tt[pos*2+1].minvalue);
tt[pos].maxvalue = max(tt[pos*2].maxvalue,tt[pos*2+1].maxvalue);
}
int query(int lp,int rp,int pos ,int id){
if(tt[pos].lp == lp && tt[pos].rp == rp){
if(id == 0)
return tt[pos].minvalue;
else
return tt[pos].maxvalue;
}
int mid = tt[pos].getmid();
if(mid >= rp)
return query(lp,rp,pos*2,id);
else if(mid < lp)
return query(lp,rp,pos*2+1,id);
else{
if(id == 0)
return min(query(lp,mid,pos*2,id),query(mid+1,rp,pos*2+1,id));
else
return max(query(lp,mid,pos*2,id),query(mid+1,rp,pos*2+1,id));
}
}
int main(){
//freopen("1.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m) != EOF){
for(int i = 1; i <= n; ++i)
scanf("%d",&num[i]);
built_tree(1,n,1);
for(int i = 1; i <= n - m + 1; ++i){
int j = i + m - 1;
aa[i].minans = query(i,j,1,0);
aa[i].maxans = query(i,j,1,1);
}
for(int i = 1; i < n - m + 1; ++i)
printf("%d ",aa[i].minans);
printf("%d\n",aa[n-m+1].minans);
for(int i = 1; i < n - m + 1; ++i)
printf("%d ",aa[i].maxans);
printf("%d\n",aa[n-m+1].maxans);
}
return 0;
}