poj_2823 线段树
题目大意
给定一行数,共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("\n"); for (int i = 0; i <= n - k; i++){ printf("%d ", gResult[i][0]); } printf("\n"); return 0; }