[Logu] P1886 & [POJ] 2823 sliding window (monotonous queue)

[Logu] P1886 & [POJ] 2823 sliding window (monotonous queue)

Title description

There is a sequence a of length n, and a window of size k. Now this one slides from the left to the right, sliding one unit at a time to find the maximum and minimum values ​​in the window after each sliding.

E.g:

The array is 1,3,-1,-3,5,3,6,7, and k=3。
Insert picture description here

Input format

There are two lines of input, the first line has two positive integers n, k. N integers in the second line, representing the sequence a

Output format

There are two lines of output, the first line is the minimum value of each window sliding, the
second line is the maximum value of each window sliding

Sample input and output

enter
8 3
1 3 -1 -3 5 3 6 7
Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7

Instructions/tips

[Data range]
For 50% data, 1<=n<=10 5 ;
for 100% data, 1<=k<=n<=10 6
a i ∈[−2 31 ,2 31 ].

Ideas

Let's take the maximum value as an example.
We know that when we are looking for the current f(i), we have compared the number of k-1 before i when we calculate f(i-1). So can we save the last result? Of course, it is mainly the largest value among the first k-1 numbers of i. The answer is yes, which requires a monotonically decreasing queue.
Using monotonic queues involves removing heads and tails:
monotonic queues have the property that all elements in the queue are either monotonically increasing or monotonically decreasing, so the minimum (maximum) value each time must be the
first k in the process of implementing the program at the head of the queue . Each element enters the queue, and each time a[k+1...n] is added to the end of the queue, the following operations are performed in the inserted element at the same time:
1. Pop all the values ​​greater than a[i] from the end of the queue
2. Insert a[ i] To the end of the queue
3. Determine whether the position of the element at the head of the team exceeds ik.
After maintaining a monotonically decreasing queue with a correct interval and strictly decreasing, the head of the queue is the maximum value of the current interval.

Code

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int ans[1000010],mnl,mnr,mxl,mxr;
struct jgt
{
    
    
	int s,x;
}mn[1000010],mx[1000010];
void pushmn(int x,int w)//单调递增 
{
    
    
	for(;mnr>=mnl&&x<=mn[mnr].s;mnr--);//删除大于x的数 
	mn[++mnr].s=x;
	mn[mnr].x=w;
	return;
}
void pushmx(int x,int w)//单调递减 
{
    
    
	for(;mxr>=mxl&&x>=mx[mxr].s;mxr--);//删除小于x的数
	mx[++mxr].s=x;
	mx[mxr].x=w;
	return;
}
int main()
{
    
    
	int i,j,n,m,x;
	scanf("%d%d",&n,&m);
	mnl=mnr=mxl=mxr=0;
	for(i=1;i<m;i++)
	{
    
    
		scanf("%d",&x);
		pushmn(x,i);
		pushmx(x,i);
	}
	for(;i<=n;i++)
	{
    
    
		scanf("%d",&x);
		pushmn(x,i);
		pushmx(x,i);
		for(j=mnl;j<=mnr&&(i-m+1>mn[j].x||mn[j].x>i);j++);//找范围内的最小值
		printf("%d ",mn[j].s);
		for(j=mxl;j<=mxr&&(i-m+1>mx[j].x||mx[j].x>i);j++);//找范围内的最大值
		ans[i]=mx[j].s;
	}
	printf("\n");
	for(i=m;i<=n;i++)
		printf("%d ",ans[i]);
	return 0;
}

STL+ fast reading fast losing

#include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
int ans[1000010];
struct jgt
{
    
    
	int s,x;
};
deque<jgt> mn;
deque<jgt> mx;
int read()//快读 
{
    
    
	int ans=0,f=1;
	char c;
	for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
	if(c=='-') f=-1;
	else ans=c-48;
	for(c=getchar();'0'<=c&&c<='9';c=getchar())ans=(ans<<3)+(ans<<1)+c-48;
	return ans*f;
}
void print(int x)
{
    
    
	if(x==0)return;
	print(x/10);
	putchar(char(x%10+'0'));
	return;
} 
void PT(int x)
{
    
    
	if(x<0)
	{
    
    
		putchar('-');
		print(-x);
		return;
	}
	if(x==0)
	{
    
    
		putchar('0');
		return;
	}
	print(x);
	return;
}
int main()
{
    
    
	int i,j,n,m,x;
	jgt t;
	n=read();
	m=read();
//	scanf("%d%d",&n,&m);
//	mnl=mnr=mxl=mxr=0;
	for(i=1;i<m;i++)
	{
    
    
		x=read();
//		scanf("%d",&x);
		for(;!mn.empty()&&x<=mn.back().s;mn.pop_back());//删除大于x的数
		t.s=x,t.x=i;
		mn.push_back(t);
		for(;!mx.empty()&&x>=mx.back().s;mx.pop_back());//删除小于x的数
		t.s=x,t.x=i;
		mx.push_back(t);
	}
	for(;i<=n;i++)
	{
    
    
		x=read();
//		scanf("%d",&x);
		for(;!mn.empty()&&x<=mn.back().s;mn.pop_back());//删除大于x的数
		t.s=x,t.x=i;
		mn.push_back(t);
		for(;!mx.empty()&&x>=mx.back().s;mx.pop_back());//删除小于x的数
		t.s=x,t.x=i;
		mx.push_back(t);
		for(;!mn.empty()&&(i-m+1>mn.front().x||mn.front().x>i);mn.pop_front());//找范围内的最小值
		PT(mn.front().s);
		putchar(' ');
//		printf("%d ",mn[j].s);
		for(;!mx.empty()&&(i-m+1>mx.front().x||mx.front().x>i);mx.pop_front());//找范围内的最大值
		ans[i]=mx.front().s;
	}
//	printf("\n");
	putchar('\n');
	for(i=m;i<=n;i++)
	{
    
    
		PT(ans[i]);
		putchar(' ');
//		printf("%d ",ans[i]);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_46975572/article/details/113096337