题目链接:https://cn.vjudge.net/contest/276251#problem/G
题目大意:给你n和m,然后问你对于(m,n)这中间的每一个数,(i-m+1,i)这个区间的最小值和最大值。
具体思路:单调队列,对于个数的控制,我们通过队列来实现一个模拟的滑动窗口。然后最值的寻找,我们可以通过控制队列保持单调递增或者单调递减来实现。
STL AC代码(耗时:10985s):
#include<iostream>
#include<stack>
#include<cmath>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
const int maxn = 1e6+100;
int minn[maxn],maxx[maxn],sto[maxn];
inline int read1()
{
int f=1,x=0;
char s=getchar();
while(s<'0' || s>'9')
{
if(s=='-')
f=-1;
s=getchar();
}
while(s>='0' && s<='9')
{
x=x*10+s-'0';
s=getchar();
}
return x*f;
}
int main()
{
int n,m;
n=read1();
m=read1();
// scanf("%d %d",&n,&m);
deque<int>q1;
deque<int >q2;
int tot=0,tmp;
for(int i=1;i<=n;i++){
sto[i]=read1();
}
for(int i=1; i<=n; i++)
{
while(!q1.empty()&&q1.front()<i-m+1)//先判断左边界有没有超出范围
q1.pop_front();
while(!q1.empty()&&sto[i]<sto[q1.back()])//保持队列单调递增
{
q1.pop_back();
}
q1.push_back(i);
if(i>=m)
minn[++tot]=q1.front();
while(!q2.empty()&&q2.front()<i-m+1)
q2.pop_front();
while(!q2.empty()&&sto[i]>sto[q2.back()])
{
q2.pop_back();
}
q2.push_back(i);
if(i>=m)
maxx[tot]=q2.front();
}
for(int i=1; i<=tot; i++)
{
if(i==1)
printf("%d",sto[minn[i]]);
else
printf(" %d",sto[minn[i]]);
}
printf("\n");
for(int i=1; i<=tot; i++)
{
if(i==1)
printf("%d",sto[maxx[i]]);
else
printf(" %d",sto[maxx[i]]);
}
printf("\n");
return 0;
}
数组模拟(耗时:7152ms)AC代码:
#include<iostream>
#include<stack>
#include<cmath>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
const int maxn = 1e6+100;
int minn[maxn],maxx[maxn],sto[maxn];
int moni[maxn];
inline int read1()
{
int f=1,x=0;
char s=getchar();
while(s<'0' || s>'9')
{
if(s=='-')
f=-1;
s=getchar();
}
while(s>='0' && s<='9')
{
x=x*10+s-'0';
s=getchar();
}
return x*f;
}
int main()
{
int n,m;
n=read1();
m=read1();
int l=1,r=0;
int tot=0;
for(int i=1; i<=n; i++)
{
sto[i]=read1();
}
for(int i=1; i<=n; i++)
{
while(l<=r&&moni[l]<i-m+1)
l++;
while(l<=r&&sto[i]<sto[moni[r]]){
r--;
}
moni[++r]=i;
if(i>=m)
minn[++tot]=moni[l];
}
l=1,r=0,tot=0;
for(int i=1; i<=n; i++)
{
while(l<=r&&moni[l]<i-m+1)
l++;
while(l<=r&&sto[i]>sto[moni[r]]){
r--;
}
moni[++r]=i;
if(i>=m)
maxx[++tot]=moni[l];
}
for(int i=1; i<=tot; i++)
{
if(i==1)
printf("%d",sto[minn[i]]);
else
printf(" %d",sto[minn[i]]);
}
printf("\n");
for(int i=1; i<=tot; i++)
{
if(i==1)
printf("%d",sto[maxx[i]]);
else
printf(" %d",sto[maxx[i]]);
}
printf("\n");
return 0;
}
(我太菜了,,,数组模拟调了半个小时。。)