BZOJ 1012 最大数maxnumber 单调队列

题意;初始序列为空,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);
	else	update(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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值