华师一附中OI组
标题:
P1886 滑动窗口
[打印本页]
作者:
admin
时间:
2018-9-11 16:07
标题:
P1886 滑动窗口
https://www.luogu.org/problemnew/show/P1886
题目描述
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
The array is [1 3 -1 -3 5 3 6 7], and k = 3.
位置
最大值
[1 3 -1] -3 5 3 6 7
3
1 [3 -1 -3] 5 3 6 7
3
1 3 [-1 -3 5] 3 6 7
5
1 3 -1 [-3 5 3] 6 7
5
1 3 -1 -3 [5 3 6] 7
6
1 3 -1 -3 5 [3 6 7]
7
输入输出格式
输入格式:
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
输入输出样例
输入样例#1:
8 3
1 3 -1 -3 5 3 6 7
输出样例#1:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
说明
50%的数据,n<=10^5
100%的数据,n<=10^6
作者:
admin
时间:
2018-9-11 16:09
单调队列经典题
作者:
倚窗倾听风吹雨
时间:
2018-9-11 16:52
#include<iostream>
using namespace std;
const int M=1000010;
int n,k,b,j=1;
int mina[M],maxa[M];
struct sque
{
int a[M],head,tail;
int q[M],p[M];
void read()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
}
void findmax()
{
head=1;
tail=0;
for(int i=1;i<=n;i++)
{
while(q[tail]<=a[i] && head<=tail)tail--;
q[++tail]=a[i];
p[tail]=i;
while(p[head]<=i-k)
head++;
if(i>=k)cout<<q[head]<<" ";
}
cout<<endl;
}
void findmin()
{
head=1;
tail=0;
for(int i=1;i<=n;i++)
{
while(q[tail]>=a[i] && head<=tail)tail--;
q[++tail]=a[i];
p[tail]=i;
while(p[head]<=i-k)
head++;
if(i>=k)cout<<q[head]<<" ";
}
cout<<endl;
}
}q;
int main()
{
q.read();
q.findmin();
q.findmax();
}
复制代码
作者:
admin
时间:
2019-11-12 10:50
这是一个很好的简单的高级数据结构的训练题,可以用很多种方法很做,
1、典型的单调队列题,用一个队列维护,新加入的数字前,先删掉比他大的元素,要是队列的长度大于k,则队头元素删掉。这样队列里面的就是最大值。
2、ST表求最大值最小值显然是可行的,每次挪动了一个,还可以继承前面计算下来的f(i,j)
3、线段树来做此题有点大材小用,但是训练下代码能力也是不错的。4、大根堆:扫描的时候,新元素加入堆,如果发现堆顶元素不在当前的扫描区间内就pop堆顶元素,知道堆顶元素在扫描区间内,输出答案。
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2