题目大意
给定一行数,共N个。有一个长度为K的窗口从左向右滑动,窗口中始终有K个数字,窗口每次滑动一个数字。求各个时刻窗口中的最大值和最小值。
题目分析
直接搜索,复杂度为O(n^2)。本题可以看做是一个区间求最大值最小值的问题,因此考虑使用线段树解决。
和用单调队列方法相比,时间复杂度O(nlogn),略慢。但也是一个不错的算法,毕竟进行区间求值,单调队列并不总是通用。
实现(c++)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<vector>
using namespace std;
#define MAX_SIZE 1000005
#define INFINITE 1 << 30
#define MAX(a, b) a > b?a:b
#define MIN(a, b) a < b?a:b
int gResult[MAX_SIZE][2];
struct Node{
int beg;
int end;
int max;
int min;
};
Node gNodes[MAX_SIZE * 4];
int gArray[MAX_SIZE];
void PushUp(int index){
int left = (index << 1) + 1;
int right = (index << 1) + 2;
gNodes[index].max = MAX(gNodes[left].max, gNodes[right].max);
gNodes[index].min = MIN(gNodes[left].min, gNodes[right].min);
}
void BuildTree(int index, int beg, int end){
gNodes[index].beg = beg;
gNodes[index].end = end;
if (beg == end){
gNodes[index].min = gNodes[index].max = gArray[beg];
return;
}
int left = (index << 1) + 1;
int right = (index << 1) + 2;
int mid = (beg + end) >> 1;
BuildTree(left, beg, mid);
BuildTree(right, mid + 1, end);
PushUp(index);
}
pair<int,int> Query(int index, int beg, int end){
if (beg > end || beg > gNodes[index].end || end < gNodes[index].beg){
return pair<int, int>(-INFINITE, INFINITE);
}
if (gNodes[index].beg >= beg && gNodes[index].end <= end){
return pair<int, int>(gNodes[index].max, gNodes[index].min);
}
int mid = (gNodes[index].beg + gNodes[index].end) >> 1;
int left = (index << 1) + 1;
int right = (index << 1) + 2;
pair<int, int> result_left = Query(left, beg, MIN(mid, end));
pair<int, int> result_right = Query(right, MAX(mid + 1, beg), end);
return pair<int, int>(MAX(result_left.first, result_right.first), MIN(result_left.second, result_right.second));
}
int main(){
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0; i < n; i++){
scanf("%d", gArray + i);
}
BuildTree(0, 0, n - 1);
pair<int, int> result;
for (int i = 0; i <= n - k; i++){
result = Query(0, i, i + k-1);
gResult[i][0] = result.first;
gResult[i][1] = result.second;
}
for (int i = 0; i <= n - k; i++){
printf("%d ", gResult[i][1]);
}
printf("
");
for (int i = 0; i <= n - k; i++){
printf("%d ", gResult[i][0]);
}
printf("
");
return 0;
}