luoguP1886 滑动窗口

发一波树状数组的版本

单调队列是最快的

树状数组也可以过

需要吸氧这里使用了手动O3

具体怎么写就是树状数组的板子题,单点修改区间查询最值,注意初始值的设置调了很久

#pragma GCC optimize(3)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000005;
int n,k,a[N],c[N],b[N];
inline int lowbit(int x){return (x&(-x));}
inline void modify1(int pos,int val)
{for(;pos<=n;pos+=lowbit(pos))c[pos]=max(c[pos],val);}
inline void modify2(int pos,int val)
{for(;pos<=n;pos+=lowbit(pos))b[pos]=min(b[pos],val);}
inline int query1(int l,int r)
{
    int ans=-0x7fffffff;
    while(r>=l)
    {
        ans=max(ans,a[r]);
        for(r--;r-lowbit(r)>=l;r-=lowbit(r))
        ans=max(ans,c[r]);
    }
    return ans;
}
inline int query2(int l,int r)
{
    int ans=0x7fffffff;
    while(r>=l)
    {
        ans=min(ans,a[r]);
        for(r--;r-lowbit(r)>=l;r-=lowbit(r))
        ans=min(ans,b[r]);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k;
    memset(c,-0x3f,sizeof(c));
    memset(b,0x3f,sizeof(b));
    for(int i=1;i<=n;i++)cin>>a[i],modify1(i,a[i]),modify2(i,a[i]);
    for(int i=k;i<=n;i++)cout<<query2(i-k+1,i)<<" ";
    cout<<endl;
    for(int i=k;i<=n;i++)cout<<query1(i-k+1,i)<<" ";
}

再发一下单调队列的,不用吸氧
版本一STL

#include<iostream>
#include<deque>
using namespace std;
const int N=1000005;
int n,k;
struct node{int v,id;}a[N];
deque<node> qmin,qmax;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i].v,a[i].id=i;
    for(int i=1;i<=n;i++)
    {
        while(!qmin.empty()&&qmin.back().v>=a[i].v)qmin.pop_back();
        qmin.push_back(a[i]);
        if(qmin.front().id==i-k)qmin.pop_front();
        if(i>=k)cout<<qmin.front().v<<" ";
    }
    cout<<endl;
    for(int i=1;i<=n;i++)
    {
        while(!qmax.empty()&&qmax.back().v<=a[i].v)qmax.pop_back();
        qmax.push_back(a[i]);
        if(qmax.front().id==i-k)qmax.pop_front();
        if(i>=k)cout<<qmax.front().v<<" ";
    }
}

版本二数组模拟

#include"iostream"
using namespace std;
const int N=1000005;
int n,k,a[N],h,t;
struct deque{int v,id;}qmax[N],qmin[N];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];	
    h=t=1;
    for(int i=1;i<=n;i++)
    {
        while(h!=t&&qmin[t-1].v>=a[i])t--;
        qmin[t].v=a[i],qmin[t++].id=i;
        if(qmin[h].id==i-k)h++;
        if(i>=k)cout<<qmin[h].v<<" ";
    }
    cout<<endl; 
    h=t=1;
    for(int i=1;i<=n;i++)
    {
        while(h!=t&&qmax[t-1].v<=a[i])t--;
        qmax[t].v=a[i],qmax[t++].id=i;
        if(qmax[h].id==i-k)h++;
        if(i>=k)cout<<qmax[h].v<<" ";
    }
}

主要是想推广一下树状数组,这个数据结构非常好,会比线段树快,还十分好写

posted @ 2019-03-28 20:11  アインツベルン  阅读(184)  评论(0编辑  收藏  举报
Live2D