[线段树]校OJ-JSOI2008最大数

博客围绕JSOI2008最大数问题展开,给定n个小于p的数,有添加和询问两个操作,添加是在序列末尾加一个数,询问是输出序列后L位最大值,采用动态开点的线段树求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JSOI2008最大数

大意

给定n个数,每个数保证小于p,下面执行两个操作

  • 添加:再当前序列末尾加上一个数
  • 询问:输出序列后L位中的最大值

思路

因为每次询问是某一段范围的最大值,用动态开点的线段树写起来更优

code

#include<bits/stdc++.h>
using namespace std;
const int M=4e5;
	int m,p,ans=0,num=0,root=0;
	char c;
	int a;
struct tree
{
	int l,r,zhi;
	#define l(o) t[o].l 
	#define r(o) t[o].r 
	#define zhi(o) t[o].zhi 
}t[4*M];
int cnt;

void add(int &p,int bh,int l,int r,int d)
{
	if(!p) p=++cnt;
	if(l==r)
	{
		zhi(p)=d;
		return;
	}
	int mid=(l+r)/2;
	if(bh<=mid) add(l(p),bh,l,mid,d);
	else add(r(p),bh,mid+1,r,d);
	zhi(p)=max(zhi(l(p)),zhi(r(p)));
}
int ask(int p,int ll,int rr,int l,int r)
{
	if(l>=ll&&r<=rr)
	{
		return zhi(p);
	}
	int mid=(l+r)/2;
	int maxx=-1;
	if(ll<=mid) maxx=ask(l(p),ll,rr,l,mid);
	if(rr>mid) maxx=max(maxx,ask(r(p),ll,rr,mid+1,r));
	return maxx; 
}
int main()
{
	scanf("%d%d",&m,&p);
	for(int i=1;i<=m;i++)
	{
		scanf("%s%d",&c,&a);
		if(c=='Q')
		{
			ans=ask(root,num-a+1,num,1,m);
			printf("%d\n",ans);
		}
		else
		{
			add(root,num+1,1,m,(ans%p+a%p)%p);
			num++;
		}
	}
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值