1. 程式人生 > >【洛谷P1886】滑動窗口

【洛谷P1886】滑動窗口

esp sca nlogn log %d 範圍 clu logs bsp

這個題數據範圍10^6,nlogn很懸,所以我們考慮用單調隊列

單調隊列的性質,保證隊列單調遞減/遞增,因此我們可以通過維護單調隊列,來方便的查詢區間最大值、最小值

#include<iostream>
#include<cstdio>
using namespace std;
struct in
{
    int zhi,wei;
}ter[1000010];
int shu[1000010],mi[1000010],mx[1000010],n,k,head,tail;
inline void cl(int x)
{
    while(ter[head].wei<x-k+1
&&head<=tail)//凡是在窗口外的一律彈出 head++; } inline void pu1(int x) { while(shu[x]<ter[tail].zhi&&head<=tail)//保證隊列單調遞增,凡是比這個數大的就都沒有可能成為答案了,因為他們入隊在前,值還大,而凡是可以與他們在一個隊列裏的就意味著有窗口能將他們一起覆蓋 tail--; ter[++tail]=(in){shu[x],x}; mi[x]=ter[head].zhi; } inline
void pu2(int x) { while(shu[x]>ter[tail].zhi&&head<=tail)//同理保持單調遞減 tail--; ter[++tail]=(in){shu[x],x}; mx[x]=ter[head].zhi; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&shu[i]); head=tail=1,mi[1
]=shu[1],ter[1]=(in){shu[1],1}; for(int i=2;i<=n;i++) cl(i),pu1(i); head=tail=1,mx[1]=shu[1],ter[1]=(in){shu[1],1}; for(int i=2;i<=n;i++) cl(i),pu2(i); for(int i=k;i<=n;i++) printf("%d ",mi[i]); printf("\n"); for(int i=k;i<=n;i++) printf("%d ",mx[i]); printf("\n"); }

【洛谷P1886】滑動窗口