zoukankan      html  css  js  c++  java
  • 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("
    ");
    	for (int i = 0; i <= n - k; i++){
    		printf("%d ", gResult[i][0]);
    	}
    	printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    ansible 2.2的源码编译安装
    存储过程-快速上手
    从库重启后报1062错误
    删除一张600万记录表的一个索引需要多长时间?
    mysql主从复制Error1205
    浅谈管理(三)如何管理资料库
    kettle之时间字段默认值为空或’0000-00-00’问题
    浅谈管理(二)项目管理
    乌龙之Ignoring query to other database问题
    一、安装
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4835793.html
Copyright © 2011-2022 走看看