RMQ- priority queue and queue monotonous training topics

Priority Queue

Priority_queue STL library refers to the use of the simulation, it is advantageous in that simple. Can be used to find the best value for the interval, the use of stack operation, the time complexity \ ([n-\ ~ n-log_2 ^ {n-2} \ {n-log_2}] \) , when a large data easily TLE

Monotonous queue

Monotone queue uses the STL deque simulation, an array may also be used and the double pointer \ ((head, tail) \) , there are two operations, the head and tail-deleted, monotone increasing or decreasing within an interval queue, linear complexity degree. Monotone queue optimization often with dp.

Deleted head

Determining whether the first element is expired - exceeds the window length, i.e., pop expired;

To tail

Determining whether a new element is greater than the last element (descending), smaller than the new element (incremented). If the principle is the last element if conditions are met, the last element must not move the head element, and therefore can be ejected;

dp optimization

Dp array of a range of monotone queue maintenance, most dp object takes a value within a certain range, and just before a
transition equation generally \ (dp [i] = dp [j] + w [i], (j + m <i) \ )

Classic question:
Luo Gu P1440 minimization within the range of m

Solution one:

ST classic table, MLE. Two-dimensional array desired range is too large, exceeding the memory limit, the speed is relatively slow

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define MAXN 2000020
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int n,m,brr[MAXN][(int)log2(MAXN)+1];
int main()
{//MLE
    scanf("%d%d",&n,&m);
    FOR2(i,1,n)
    {
        scanf("%d",&brr[i][0]);
    }
    int logm=log2(m);
    for(int h=1;h<=logm;h++)
    {
        for(int i=1;i+(1<<h)-1<=n;i++)
        {
            brr[i][h]=min(brr[i][h-1],brr[i+(1<<h-1)][h-1]);
        }
    }
    int minn=INF;
    cout<<0<<endl;
    for(int i=2;i<=n;i++)
    {

        if(i<=m+1){
            minn=min(minn,brr[i-1][0]);
            cout<<minn<<endl;
            continue;
        }
        cout<<min(brr[i-m][logm],brr[i-(1<<logm)][logm])<<endl;
    }
    return 0;
}

Solution two:

ST optimize memory table, TLE, using a layer of double-counting an array of values ​​to solve the problem of memory, but the ST table iteration slow disadvantage leads to TLE

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define MAXN 2000020
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int arr[MAXN],n,m,brr[MAXN];
int main()
{//TLE
    scanf("%d%d",&n,&m);
    FOR2(i,1,n)
    {
        scanf("%d",&brr[i]);
        arr[i]=brr[i];
    }
    int logm=log2(m);
    for(int h=1;h<=logm;h++)
    {
        for(int i=1;i+(1<<h)-1<=n;i++)
        {
            brr[i]=min(brr[i],brr[i+(1<<h-1)]);
        }
    }
    int minn=INF;
   printf("0\n");
    for(int i=2;i<=n;i++)
    {

        if(i<=m+1){
            minn=min(minn,arr[i-1]);
            printf("%d\n",minn);
            continue;
        }
        printf("%d\n",min(brr[i-m],brr[i-(1<<logm)]));
    }
    return 0;
}

Solution three:

Priority queue, 550ms before, but the root of the heap adjust speed or slightly slower

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define MAXN 2000020
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
typedef struct{
    int val;
    int pos;
}NODE;NODE nodes[MAXN];
int n,m;
struct cmp{
    bool operator() (NODE n1,NODE n2)
    {
        return n1.val>=n2.val; //小根堆 
    }
};
priority_queue<NODE,vector<NODE>,cmp>q;
int main()
{
    scanf("%d%d",&n,&m);
    int minp=0,minn=INF;
    FOR2(i,1,n)
    {
        scanf("%d",&nodes[i].val);
        nodes[i].pos=i;
        if(i==1)cout<<0<<endl;
        else 
        {
            while(m+q.top().pos<i)q.pop();//是否过期 
            printf("%d\n",q.top().val);
        }
        if(i!=n)q.push(nodes[i]);
    }
    return 0;
}

Solution four:

Monotone queue, 400ms, linear complexity, positive solution

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define freopenin(a) freopen(a,"r",stdin);
#define freopenout(a) freopen(a,"w",stdout);
#define MAXN 2000100
#define MOD 10007
using namespace std;
typedef struct{
    int val,pos;
}NODE;NODE nodes[MAXN];
int n,m;
deque<NODE>q;//递增 
int main()
{
    scanf("%d%d",&n,&m);
    FOR2(i,1,n)
    {
        scanf("%d",&nodes[i].val);
        nodes[i].pos=i;
        
        while(!q.empty()&&q.back().val>=nodes[i].val)q.pop_back();
        while(!q.empty()&&q.front().pos+m<=i)q.pop_front();
        q.push_back(nodes[i]);
        if(i==1) printf("0\n");
        if(i!=n)
        {
            printf("%d\n",q.front().val);
        }
        
    }
    return 0;
}

Luo Gu P1886 sliding window

Solution one:

Priority queue, the root of the heap adjusted complexity \ (O (n \ log_2 { n}) \) disadvantage leads simply can not through the second point, direct TLE

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define freopenin(a) freopen(a,"r",stdin);
#define freopenout(a) freopen(a,"w",stdout);
#define MAXN 1000100
#define MOD 10007
using namespace std;
typedef struct{
    int val,pos;
}NODE;NODE nodes[MAXN];
struct cmp{
    bool operator() (NODE n1,NODE n2)
    {
        return n1.val>=n2.val;
    }
};
struct cmp2{
    bool operator() (NODE n1,NODE n2)
    {
        return n1.val<=n2.val;
    }
};
priority_queue<NODE,vector<NODE>,cmp>q;//小根堆 
priority_queue<NODE,vector<NODE>,cmp2>q2;//大根堆 
int ansx[MAXN];
int ansn[MAXN];
int n,k;
int main()
{
    cin>>n>>k;
    FOR2(i,1,n)
    {
        scanf("%d",&nodes[i].val);
        nodes[i].pos=i;
        q.push(nodes[i]);
        q2.push(nodes[i]);
        if(i-k>=0)
        {
            while(q.top().pos+k<=i)q.pop();
            while(q2.top().pos+k<=i)q2.pop();
            ansx[i-k]=q2.top().val;
            ansn[i-k]=q.top().val;
        }
    }
    FOR(i,0,n-k+1)printf("%d ",ansn[i]);
    printf("\n");
    FOR(i,0,n-k+1)printf("%d ",ansx[i]);
    return 0;
}

Solution two:

Monotone queue, 550ms off, linear complexity NB

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x3f3f3f3f;
#define freopenin(a) freopen(a,"r",stdin);
#define freopenout(a) freopen(a,"w",stdout);
#define MAXN 1000100
#define MOD 10007
using namespace std;
typedef struct{
    int val,pos;
}NODE;NODE nodes[MAXN];
deque<NODE>q1;//递减 
deque<NODE>q2;//递增 
int ansx[MAXN],ansn[MAXN];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    FOR(i,0,n)
    {
        scanf("%d",&nodes[i].val);
        nodes[i].pos=i;
        while(!q1.empty()&&q1.back().val>=nodes[i].val)q1.pop_back();
        while(!q2.empty()&&q2.back().val<=nodes[i].val)q2.pop_back();
        while(!q1.empty()&&q1.front().pos+m<=i)q1.pop_front();
        while(!q2.empty()&&q2.front().pos+m<=i)q2.pop_front();
        q1.push_back(nodes[i]);
        q2.push_back(nodes[i]);
        ansx[i]=q1.front().val;
//      for(int i=0;i<q1.size();i++)cout<<q1[i].val<<" ";
//      cout<<q1.size()<<endl;
//      cout<<endl;
        ansn[i]=q2.front().val;
    }
    FOR(i,m-1,n)printf("%d ",ansx[i]);
    printf("\n");
    FOR(i,m-1,n)printf("%d ",ansn[i]);
    
    return 0; 
}

JZOJ P2944 flames transfer

The meaning of problems

A string of numbers, must have at least two points are selected, and the minimum point Q selected within each window m

The basic idea

Dp array of monotonically queue optimization, such that the minimum value of the currently selected point plus m states before, the summation dp.
Transfer equation \ (dp [i] = dp [j] + w [i], (im <j <i) \)

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
#define INF  0x7f7f7f7f;
#define freopenin(a) freopen(a,"r",stdin);
#define freopenout(a) freopen(a,"w",stdout);
#define MAXN 1000100
#define MOD 10007
using namespace std;
typedef struct{
    ll val,pos;
}NODE;NODE dp[MAXN];
ll w[MAXN],n,m;
deque<NODE>q;
int main()
{
    scanf("%d%d",&n,&m);
    dp[0]={0,0};q.push_back(dp[0]);
    FOR2(i,1,n)
    {
        scanf("%d",&w[i]);
        dp[i].pos=i;
        while(!q.empty()&&q.front().pos+m<i) q.pop_front();
        dp[i].val=q.front().val+w[i];
        while(!q.empty()&&q.back().val>dp[i].val) q.pop_back();
        q.push_back(dp[i]);
    }
    ll ans=INF;
    FOR2(i,n-m+1,n)
    {
        ans=min(ans,dp[i].val);     
    }
    printf("%d\n",ans);
    return 0;
    
}

Attached manual using arrays and pointers monotone queue, fast 20ms

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
int n,m;
int w[100001];
int que[100001],head=0,tail=0;
int f[100001];
int main()
{
    scanf("%d%d",&n,&m);
    int i,j;
    for (i=1;i<=n;++i)
        scanf("%d",&w[i]);
    memset(f,127,sizeof f);
    f[0]=0;
    que[0]=0;
    for (i=1;i<=n;++i)
    {//对f做单调队列 
        if (que[head]<i-m)
            ++head;//将超出范围的队头删掉
        f[i]=f[que[head]]+w[i];//转移(用队头)
        while (head<=tail && f[que[tail]]>f[i])
            --tail;//将不比它优的全部删掉
        que[++tail]=i;//将它加进队尾
    }
    for(int i=0;i<=n;i++)
    {
        cout<<que[i]<<" ";
    }
    cout<<endl;
    for(int i=0;i<=n;i++)
    {
        cout<<f[i]<<" ";
    }
    cout<<endl;
    int ans=0x7f7f7f7f;
    for (i=n-m+1;i<=n;++i)
        ans=min(ans,f[i]);
    printf("%d\n",ans);
}

Guess you like

Origin www.cnblogs.com/tldr/p/11269332.html