题意:大概就是有三种操作吧,第一种在队列后面加入新人,引入一个不耐烦程度,第二种第一个人出队(直接让头结点的序号+1即可),第三种统计在队伍里面不耐烦程度最高的数(PS:随着操作的进行队列中每一个人的不耐烦程度+1),刚开始我是将每个节点加入线段树中,对于每个操作,打上lazy标记,用线段树区间维护,然后TLE了,改了又改,在室友的提醒下,原来我可以把每个加入的节点都统一在第一个节点时插入,只要保证取最大就行,每次执行操作三,选出最大的,然后加上输入第几个操作即可,本来很水的一道题,硬是写了这么久,还是太菜了233333333,直接贴代码了;
#include<algorithm> #include<iostream> #include<queue> #include<stack> #include<vector> #include<map> #include<set> #include<cstring> #include<cstdio> #include<cmath> #define N 400005 #define INF 0x3f3f3f3f using namespace std; typedef struct node { int x; int y; int date; int ma; } node; node a[4*N]; void built(int root,int first,int end) { if(first==end) { a[root].x=first; a[root].y=end; a[root].date=0; a[root].ma=0; return ; } int mid=(first+end)/2; built(root*2,first,mid); built(root*2+1,mid+1,end); a[root].x=a[root*2].x; a[root].y=a[root*2+1].y; a[root].date=0; a[root].ma=0; } void Q(int root,int first,int end,int e,int p) { if(first==e&&end==e) { a[root].date=p; return ; } int mid=(first+end)/2; if(e<=mid) Q(2*root,first,mid,e,p); else Q(2*root+1,mid+1,end,e,p); a[root].date=max(a[root*2].date,a[root*2+1].date); } int sum; void M(int root,int first,int end,int r,int l) { if(first>=r&&end<=l) { sum=max(sum,a[root].date); return ; } int mid=(first+end)/2; if(r<=mid) M(root*2,first,mid,r,l); if(l>mid) M(root*2+1,mid+1,end,r,l); a[root].date=max(a[root*2].date,a[root*2+1].date); } int main() { int m; while(scanf("%d",&m)==1) { int n,k; built(1,1,m); int fi=1; int en=0; int ans=0; for(int i=1; i<=m; i++) { scanf("%d",&n); if(n==1) { scanf("%d",&k); en++; Q(1,1,m,en,k-i+1); } else if(n==2) { fi++; } else if(n==3) { sum=-INF; M(1,1,m,fi,en); printf("%d ",sum+i-1); } } } return 0; }