BZOJ 1012 最大数maxnumber 单调队列

来源:互联网 发布:榕基软件 编辑:程序博客网 时间:2024/06/06 16:46
题意;初始序列为空,Q次操作.Q,D<=2e5
op1:询问末尾Li个数的最大值 op2:向末尾插入x+上一次的查询的答案%D.(在线)

若一个数右边有比它大的数,则查询末尾最值时可以将该数淘汰.

单调栈维护第i大的位置.每次二分找到第一个大于n-L+1的位置即可.次二分找到第一个大于n-L+1的位置即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=4e5+20;const ll inf=1e18;ll a[N],top,num[N];int main(){int Q,D;char ch[10];while(cin>>Q>>D){ll n=0,x,ans,t=0,top=0;while(Q--){scanf("%s%lld",ch,&x);if(ch[0]=='A'){x=(x+t)%D;num[++n]=x;while(top&&x>=num[a[top]])top--;a[++top]=n;}else{int y=lower_bound(a+1,a+1+top,n-x+1)-a;t=num[a[y]];printf("%lld\n",t);}}}return 0;}


线段树维护最值,对于长度以外的位置,初始为-inf即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=4e5+20;const ll inf=1e18;struct node{ll l,r,mx;}t[N*4];void push_up(int o){t[o].mx=max(t[o<<1].mx,t[o<<1|1].mx);}void build(int o,int l,int r){t[o].l=l,t[o].r=r;if(l==r){t[o].mx=-inf;return;}int m=l+r>>1;build(o<<1,l,m),build(o<<1|1,m+1,r);push_up(o);}void update(int o,int pos,ll x){int l=t[o].l,r=t[o].r,m=l+r>>1;if(l==r){t[o].mx=x;return;}if(pos<=m) update(o<<1,pos,x);elseupdate(o<<1|1,pos,x);push_up(o);}ll query(int o,int ql,int qr){int l=t[o].l,r=t[o].r,m=l+r>>1;if(l>=ql&&r<=qr)return t[o].mx;ll res=0;if(ql<=m) res=max(res,query(o<<1,ql,qr));if(qr>m) res=max(res,query(o<<1|1,ql,qr));return res;}int main(){int Q,D;char ch[10];while(cin>>Q>>D){ll n=0,x,ans,t=0;build(1,1,100010);while(Q--){scanf("%s%lld",ch,&x);if(ch[0]=='A')n++,update(1,n,(x+t)%D);else{t=query(1,n-x+1,n);;printf("%lld\n",t);}}}return 0;}