POJ2823単調なキュー
問題のアドレスpoj.org/problem?id=2823
ビデオ説明アドレスhttps://www.bilibili.com/video/av23189029?from=search&seid=7739016115400904464
長さNの配列を指定すると、長さKのスライディングウィンドウが左端から右端に移動します。ウィンドウが1ビット右に移動するたびに、K個のウィンドウしか表示されません。あなたの仕事は、各位置でのウィンドウの最大値と最小値を見つけることです。
単調なキューには、キュー内のすべての要素が単調に増加または減少するという特性があるため、毎回の最小(最大)値はキューの先頭になければなりません。
プログラムの実装プロセスでは、最初のk要素がチームに追加され、次にa [k + 1 ... n]がチームの最後に毎回追加され、挿入された要素で次の操作が同時に実行されます。
1.キューの最後でa [i]より大きいすべての値をポップアウトします
2.行の最後にa [i]を挿入します
3.チームのヘッドエレメントの位置がikを超えているかどうかを判断する
各間隔の最大値を見つけるという点では、値が大きく位置が低い要素が役立ちます。この数は間隔の最大値である可能性が高いため、新しく追加された数よりも小さい数を取り出す必要がありますキュー。
具体的には、間隔の最大値と間隔の最小値をそれぞれ処理する2つの両端キューを確立できます。
ACコード:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<cstdlib>
using namespace std;
#define scan(n) scanf("%d",&n)
#define ll long long
struct node
{
int pos,val;
}a;
deque<node>maxq,minq;
int ma[1000005],mi[1000005];
int main()
{
int n,k,x,i;
scan(n);
scan(k);
while(!maxq.empty())
maxq.pop_back();
while(!minq.empty())
minq.pop_back();
for(i=1;i<k;i++)
{
scanf("%d",&x);
while(!maxq.empty()&&maxq.back().val<=x)
maxq.pop_back();
while(!minq.empty()&&minq.back().val>=x)
minq.pop_back();
a.pos=i,a.val=x;
maxq.push_back(a);
minq.push_back(a);
}
for(i=k;i<=n;i++)
{
while(!maxq.empty()&&maxq.front().pos<i-k+1)//先踢掉超出范围的
maxq.pop_front();
while(!minq.empty()&&minq.front().pos<i-k+1)
minq.pop_front();
scanf("%d",&x);
while(!maxq.empty()&&maxq.back().val<=x)//再踢掉非最优解
maxq.pop_back();
while(!minq.empty()&&minq.back().val>=x)
minq.pop_back();
a.pos=i,a.val=x;
maxq.push_back(a);
minq.push_back(a);
ma[i]=maxq.front().val;
mi[i]=minq.front().val;
}
printf("%d",mi[k]);
for(i=k+1;i<=n;i++)
printf(" %d",mi[i]);
printf("\n");
printf("%d",ma[k]);
for(i=k+1;i<=n;i++)
printf(" %d",ma[i]);
printf("\n");
return 0;
}