单调队列
题意:
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
解析:
最大值队列,单调递减
最小值队列,单调递增
模拟算法步骤
首先k==3,取max:
1.(1,1)预入队,max=1,队空直接入队 left=1,rigjt=1
2.(3,2)预入队,max=3,去掉比3小的元素,(1,1)出队,出队结束,(3,2)入队
3.(-1,3)预入度,max=3,出队结束,(-1,3)入队
4.(-3,5)预入队,max=3,出队结束,(-3,4)入队
5.(5,5)预入队,max=5,(3,2),(-1,3),(-3,5)出队,出队结束,(5,5)入队,
6.(3,3)预入队,max=5,出队结束,
7.(6,6)预入队,max=6,(5,5),(3,3)出队,出队结束
8.(7,7)预入队,max=7,(6,6)出队,出队结束
输出答案的时候要判断队列首是否大于i-m+1
这里用数组实现,que保存单调队列的坐标
移窗问题:
每次移动一个距离,求k范围内的最大值和最小值
可以用单调队列或者优先队列解决
单调队列写法:
ac:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define MAXN 1000005
using namespace std;
int a[MAXN];
int queA[MAXN],queB[MAXN];//记录坐标
int ansA[MAXN],ansB[MAXN];
/*
最大值队列,单调递减
最小值队列,单调递增
*/
void quemax(int st,int ed,int m)
{
int left=1,right=0;
for(int i=st;i<=ed;i++)
{
while(right>=left&&a[queA[right]]<=a[i])right--;//删掉比a[i]小的
queA[++right]=i;//压入队列
if(i-m+1>=1)//防止越界
{
while(queA[left]<i-m+1)left++;//去掉队列中i已经小于i-m+1的元素
ansA[i]=a[queA[left]];
}
}
}
void quemin(int st,int ed,int m)
{
int left=1,right=0;
for(int i=st;i<=ed;i++)
{
while(right>=left&&a[queB[right]]>=a[i])right--;//删掉比a[i]大的
queB[++right]=i;
if(i-m+1>=1)
{
while(queB[left]<i-m+1)left++;//去掉队列中i已经小于i-m+1的元素
ansB[i]=a[queB[left]];
}
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
quemin(1,n,m);
quemax(1,n,m);
for(int i=m;i<n;i++)
printf("%d ",ansB[i]);
printf("%d\n",ansB[n]);
for(int i=m;i<n;i++)
printf("%d ",ansA[i]);
printf("%d\n",ansA[n]);
}
return 0;
}
优先队列写法:
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#define MAXN 1000005
using namespace std;
struct node
{
int x,j;
friend bool operator <(node a,node b)
{
return a.x>b.x;
}
}ee[MAXN];
struct node2
{
int x,j;
friend bool operator <(node2 a,node2 b)
{
return a.x<b.x;
}
}dd[MAXN];
priority_queue<node> quex;
priority_queue<node2> quen;
int aa[MAXN],bb[MAXN];
int ac=0,bc=0;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&ee[i].x),ee[i].j=i;
dd[i].x=ee[i].x;
dd[i].j=i;
}
for(int i=1;i<k;i++)
{
quex.push(ee[i]);
quen.push(dd[i]);
}
for(int i=k;i<=n;i++)
{
quex.push(ee[i]);
quen.push(dd[i]);
while(quex.top().j+k<=i)
{
quex.pop();
if(quex.empty())
break;
}
while(quen.top().j+k<=i)
{
quen.pop();
if(quen.empty())
break;
}
aa[ac++]=quex.top().x;
bb[bc++]=quen.top().x;
}
for(int i=0;i<=n-k;i++)
{
printf("%d",aa[i]);
if(i!=n-k)
printf(" ");
else
printf("\n");
}
for(int i=0;i<=n-k;i++)
{
printf("%d",bb[i]);
if(i!=n-k)
printf(" ");
else
printf("\n");
}
return 0;
}
志愿者选拔
数据较大建议使用scanf,printf 不推荐使用STL
解析:
单调队列
ac:
#include<stdio.h>
#include<string.h>
#define maxn 1000005
using namespace std;
struct node
{
int x,val;
}que[maxn];
char name[6],na[10],start[12];
int rp;
int i,j,k,head=0,tail=-1,last=0,K=1;
void push(int rp)
{
while(tail>=head&&que[tail].val<=rp)
tail--;
que[++tail]={K++,rp};
}
void query()
{
while(tail>=head&&que[head].x<=last) head++;
if(tail>=head)
printf("%d\n",que[head].val);
else
printf("-1\n");
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
i,j,k,head=0,tail=-1,last=0,K=1;
scanf("%s",start);
while(scanf("%s",name)!=EOF)
{
if(name[0]=='E')
break;
if(name[0]=='C')
{
scanf("%s%d",na,&rp);
push(rp);
}
else if(name[0]=='Q')
{
query();
}
else
last++;//右移
}
}
return 0;
}