【单调队列学习】 POJ 2823 FZU 1894

POJ 2823 Sliding Window

首先 这题因为是在神奇的POJ上, 所以C++和G++可能又有某些玄学差别。

这次是交C++过了, G++T掉。。。

这题就是比较裸的维护一个区间最大值与最小值。

一条宏定义偷师的别人代码(谢谢巨巨)

#include<iostream>
#include <cstdio>
#define ll long long
#define pd (!x && f[tail-1]>a[i]) || (x && f[tail-1]<a[i])
using namespace std;
const int N = 1e6+3;
int n, m, k;
int a[N];
int f[N], in[N];
void getla(int x){
    int head ,  tail;
    head = tail = 0;
    for(int i=0;i<n;i++){
        while(head<tail && (pd)) tail--;
        f[tail] = a[i];
        in[tail] = i;
        tail++;
        while(in[head] <= i-k) head++;
        if(i>=k-1){
            printf("%d%c",f[head],i==n-1?'\n':' ');
        }
    }
}
int main()
{
    scanf("%d%d", &n, &k);
        for(int i=0;i<n;i++){
            scanf("%d", &a[i]);
        }
        getla(0);
        getla(1);
    return 0;
}

FZU 1894 志愿者选拔

这题选择的模型应该是单调递减的队列维护每个人的人品值(每个人还应有一个入队时的序号方便出队)。

这个出队的写出来感觉真的很神奇。

造几个数据自己跑一下大概就能理解。

#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1000003;
struct node{
    int index;
    int rp;
};
node f[N];
void solve(){
    char ask[10], name[10];
    int head, tail, tprp, cnt = 0, leave =1;
    head = tail = 0;
    while(scanf("%s", ask)!=EOF){
        if(ask[0] == 'E') return ;
        if(ask[0] == 'G'){
            while(head<tail && f[head].index<=leave)
                head++;
            leave++;
        }
        if(ask[0] == 'Q'){
            if(head<tail)
                printf("%d\n",f[head].rp);
            else puts("-1");
        }
        if(ask[0] == 'C'){
            scanf("%s%d", name, &tprp);
            while(head<tail && tprp>f[tail-1].rp)
                tail--;
            f[tail].index = ++cnt;
            f[tail++].rp = tprp;
        }
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        solve();
    }
    return 0;
}





猜你喜欢

转载自blog.csdn.net/khn64/article/details/80784938