此处有
目录↑
http://acm.xidian.edu.cn/problem.php?id=1156
[ 提交 ][ 状态 ][ 讨论版 ]
1156: 等待队列
时间限制: 1 Sec 内存限制: 128 MBhttp://acm.xidian.edu.cn/problem.php?id=1156
[ 提交 ][ 状态 ][ 讨论版 ]
题目描述
输入
输出
对于每个第 3 类操作,输出 1 行,表示队列中所有人不耐烦程度的最大值。
样例输入
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;
}
解法二:单调队列
官方题解:
待完成