我用的双端队列来做的
题意就不讲了吧。可以看出来最大值和最小值是同一个问题,改一下大于号和小于号就行了。所以我只讲怎么求最大值吧。
定义一个双端队列(相当于queue两端都可以插入或弹出,可以自行百度)
deque<pair> a,b;
pair的第一维被我称为时效性,第二位就是它自己的值。
每次操作,在前面弹出所以已失效的点;
然后再看队尾,如果点的值比当前p[i]小,也弹出;
最后把p[i]加到队尾
a.push_back(make_pair(i+k-1,p[i]));
i+k-1就是她的时效性,p[i]是她的点值
然后最大值的操作就完了
(最小值就不讲了吧)
最后附上代码
#include<bits/stdc++.h>
using namespace std;
deque <pair<int,int> > a,b;
int n,k,p[1000005];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>p[i];
a.push_back(make_pair(k,p[1]));
b.push_back(make_pair(k,p[1]));
for(int i=2;i<=k-1;i++)
{
if(a.front().first<i) a.pop_front();
while(!a.empty())
{
if(a.back().second>p[i])
{
a.pop_back();
continue;
}
break;
}
a.push_back(make_pair(i+k-1,p[i]));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(b.front().first<i) b.pop_front();
while(!b.empty())
{
if(b.back().second<p[i])
{
b.pop_back();
continue;
}
break;
}
b.push_back(make_pair(i+k-1,p[i]));
}
for(int i=k;i<=n;i++)
{
while(!a.empty()&&a.front().first<i) a.pop_front();
while(!a.empty())
{
if(a.back().second>p[i])
{
a.pop_back();
continue;
}
break;
}
a.push_back(make_pair(i+k-1,p[i]));
cout<<a.front().second<<" ";
}
cout<<endl;
for(int i=k;i<=n;i++)
{
while(!b.empty()&&b.front().first<i) b.pop_front();
while(!b.empty())
{
if(b.back().second<p[i])
{
b.pop_back();
continue;
}
break;
}
b.push_back(make_pair(i+k-1,p[i]));
cout<<b.front().second<<" ";
}
return 0;
}