单调队列

单调队列:是指队列中存在递增/递减。
这个在求Sliding Window的时候特别好用。
比如。需要求这一区间的最小值。
则只需维持一个递增队列,当存在比队列中更小的数字时,将队列中所有比这个数大的都pop出去。
如果用stl中的list来的话,不能使用二分法。来快速pop出。
所以还是使用数组来模拟队列,即快又简单。
附poj 2823 ac代码

#include <iostream>
#include <cassert>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <climits>
#include <functional>
#include <list>
#include <cstdlib>
#include <set>
#include <stack>
#include <map>
#include <algorithm>

#define ll long long
using namespace std;

#define MAXN 1000010

int minList[MAXN];
int minh,mint;
int maxList[MAXN];
int maxh,maxt;
int alldata[MAXN];


int minFront(){
	return minList[minh];
}

int maxFront(){
	return maxList[maxh];
}


void minPopFornt(){
	minh++;
}

void maxPopFornt(){
	maxh++;
}

void minPushBack(int v){
	int l = minh;
	int r = mint-1;
	while(l<=r){
		int mid = (l+r)>> 1;
		if ( minList[mid] <= v ){
			l = mid+1;
		}else{
			r = mid-1;
		}
	}
	mint = l;
	minList[mint++] = v;
}


void maxPushBack(int v){
	int l = maxh;
	int r = maxt-1;
	while(l<=r){
		int mid = (l+r)>> 1;
		if ( maxList[mid] >= v ){
			l = mid+1;
		}else{
			r = mid-1;
		}
	}
	maxt = l;
	maxList[maxt++] = v;
}




int main(){
	int n,k;
	scanf("%d%d",&n,&k);

	k %= n;

	int v;

	if ( k == 1 ){
		vector<int> vec(n);
		for( int i=0;i<n;++i ){
			scanf("%d",&v);
			vec[i] = v;
		}
		for( int i=0;i<n;++i ){
			printf("%d ",vec[i]);
		}
		printf("\n");

		for( int i=0;i<n;++i ){
			printf("%d ",vec[i]);
		}
		printf("\n");
		return 0;
	}
	if ( k == 0 ){
		int mi = INT_MAX;
		int ma = INT_MIN;
		for( int i=0;i<n;++i ){
			scanf("%d",&v);
			mi = min(mi,v);
			ma = max(ma,v);
		}
		printf("%d\n%d\n",mi,ma);
		return 0;
	}

	//vector<int> minVec(n-k+1);
	//vector<int> maxVec(n-k+1);

	for( int i=0;i<n;++i ){
		scanf("%d",&v);
		alldata[i] = v;
	}

	int datah=0;
	int datat=k;
	for( int i=0;i<k;++i ){
		v = alldata[i];
		minPushBack(v);
		maxPushBack(v);
	}
	datah=0;
	datat = k;

	for( int i=k;i<n;++i ){
		printf("%d ",minFront());
		if ( alldata[datah] == minFront() ){
			minPopFornt();
		}
		datah++;
		minPushBack(alldata[i]);
		datat++;
	}
	printf("%d\n",minFront());

	datah=0;
	datat = k;
	for( int i=k;i<n;++i ){
		printf("%d ",maxFront());
		if ( alldata[datah] == maxFront() ){
			maxPopFornt();
		}
		datah++;
		maxPushBack(alldata[i]);
		datat++;
	}
	printf("%d\n",maxFront());

	return 0;
}
posted @ 2021-11-02 17:19  传说中的水牛  阅读(27)  评论(0编辑  收藏  举报