我的心愿是世界和平!
题目描述:第一行给数字n,k,接下来一行给出n个数字,在每k个数字中找到他的最大最小值。输出有两行,分别有n-k+1个数,第一行为最小值,第二行为最大值。注意:n的范围为1e6,暴力会超时。
思路:维护一个单调递减的队列,例如 3 2 5 4,3为首,直接入队列(3),2比3小,入队列(3 2),5比2大,2出队列,5比3大,3出队列(5),4比5小,入队列(5 4),这样,队首即为当前数据的最大值,在此题中,需要记录队列中数据的位置,若已经超出k个,则队首出队列。单增队列同上。
建议使用双端队列,若用数组模拟双端队列,需注意下标的控制。
样例:8 3
1 3 -1 -3 5 3 6 7
// -1 -3 -3 -3 3 3
//3 3 5 5 6 7
3 2
3 2 1
//2 1
//3 2
8 3
-1 2 3 4 5 -9 6 2
//-1 2 3 -9 -9 -9
//3 4 5 5 6 6
双端队列
#include<iostream>
#include<queue>
#include<cstdio>
#define sf scanf
const int M=1e6+10;
using namespace std;
struct node
{
int x;
int y;
} s[M+50];
void Min_Max(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)
{
if(q.empty()||s[i].x>=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x<q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
if(q.empty()||s[i].x>=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x<q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
while(q.back().y-q.front().y>=k)
q.pop_front();
cout<<" "<<q.front().x;
}
cout<<endl;
}
void Max_Min(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)
{
if(q.empty()||s[i].x<=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x>q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
if(q.empty()||s[i].x<=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x>q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
while(q.back().y-q.front().y>=k)
q.pop_front();
cout<<" "<<q.front().x;
}
}
int main()
{
int n,k,i,j;
sf("%d%d",&n,&k);
for(i=1; i<=n; i++)
{
sf("%d",&s[i].x);
s[i].y=i;
}
Min_Max(n,k);
Max_Min(n,k);
}
数组模拟
#include<stdio.h>
struct point
{
int value;
int num;
} max[1000001],min[1000001];
int s[1000001],ss[1000001];
int main()
{
int t,i,j,m,n,k,p,maxp=0,minp=0,maxq=0,minq=0;
scanf("%d%d",&n,&k);
if(k==1)
{
for(i=0; i<n; i++)
{
scanf("%d",&m);
s[i]=m;
ss[i]=m;
}
t=n;
}
else
{
scanf("%d",&m);
max[0].value=min[0].value=m;
max[0].num=min[0].num=0;
p=0;
for(i=1; i<k-1; i++)
{
scanf("%d",&m);
if(m<=max[maxq].value)
{
max[++maxq].value=m;
max[maxq].num=i;
}
else
{
while(maxq>=maxp&&m>max[maxq].value)
maxq--;
max[++maxq].value=m;
max[maxq].num=i;
}
if(m>=min[minq].value)
{
min[++minq].value=m;
min[minq].num=i;
}
else
{
while(minq>=maxp&&m<min[minq].value)
minq--;
min[++minq].value=m;
min[minq].num=i;
}
}
t=0;
for(i=k-1; i<n; i++)
{
scanf("%d",&m);
while(max[maxp].num<p)
maxp++;
while(min[minp].num<p)
minp++;
if(m<=max[maxq].value)
{
max[++maxq].value=m;
max[maxq].num=i;
}
else
{
while(maxq>=maxp&&m>max[maxq].value)
maxq--;
max[++maxq].value=m;
max[maxq].num=i;
}
if(m>=min[minq].value)
{
min[++minq].value=m;
min[minq].num=i;
}
else
{
while(minq>=minp&&m<min[minq].value)
minq--;
min[++minq].value=m;
min[minq].num=i;
}
s[t]=min[minp].value;
ss[t]=max[maxp].value;
t++;
p++;
}
}
for(i=0; i<t; i++)
printf("%d ",s[i]);
printf("\n");
for(i=0; i<t; i++)
printf("%d ",ss[i]);
}