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;
}

 

posted @ 2015-09-24 16:42  农民伯伯-Coding  阅读(328)  评论(0编辑  收藏  举报