XDU-1156 等待队列 (线段树||单调队列)

此处有 目录↑

1156: 等待队列

时间限制:  1 Sec   内存限制:  128 MB
http://acm.xidian.edu.cn/problem.php?id=1156
[ 提交 ][ 状态 ][ 讨论版 ]

题目描述

XDU-1156 等待队列 (线段树||单调队列)_第1张图片

输入

XDU-1156 等待队列 (线段树||单调队列)_第2张图片

输出

对于每个第 类操作,输出 行,表示队列中所有人不耐烦程度的最大值。

样例输入

8
1 5
1 5
1 5
3
2
3
1 20
3

样例输出

8
9
21

解法一:线段树

比赛时一眼看出线段树能做,特别激动,第一次用上线段树了...

线段树维护区间最大值即可

初始化一个区间为[1,n]的线段树,操作1在点tail处添加,操作2直接修改查询区间(head++)即可,操作3直接查询[head,n]的区间最大值


看了题解以后发现可以用单调队列写,暂时先放着吧...

#include <cstdio>
#include <algorithm>

#define lson (i<<1)
#define rson ((i<<1)|1)

using namespace std;

const int INF=0x3f3f3f3f;

int n,ope,X,head,tail,L,R;

struct Node {
    int l,r,mx;
}tr[400005];

void build(int i,int l,int r) {
    tr[i].l=l;
    tr[i].r=r;
    tr[i].mx=-INF;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
}

void modify(int i) {//更改点L上的值
    if(tr[i].l==tr[i].r) {
        tr[i].mx=X;
        return ;
    }
    if(L<=tr[lson].r)
        modify(lson);
    else
        modify(rson);
    tr[i].mx=max(tr[lson].mx,tr[rson].mx);
}

int query(int i) {//查找区间[L,R]上的最大值
    if(L<=tr[i].l&&tr[i].r<=R) {
        return tr[i].mx;
    }
    int mx=-INF;
    if(L<=tr[lson].r)
        mx=max(mx,query(lson));
    if(tr[rson].l<R)
        mx=max(mx,query(rson));
    return mx;
}

int main() {
    while(1==scanf("%d",&n)) {
        build(1,1,n);
        head=tail=1;
        for(int i=0;i<n;++i) {
            scanf("%d",&ope);
            if(ope==1) {
                scanf("%d",&X);
                X-=i;//不耐烦程度都处理成时间0时的,方便查询最大值
                L=tail++;
                modify(1);
            }
            else if(ope==2) {
                ++head;//队首元素出队,即查询区间往后推
            }
            else {
                L=head;
                R=n;//令区间右界为n,减少递归次数
                printf("%d\n",query(1)+i);
            }
        }
    }
    return 0;
}


解法二:单调队列

官方题解:



待完成

你可能感兴趣的:(线段树,xdu)