对于每个第 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; }
官方题解:
待完成