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

Posted zero_orez6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[线段树]校OJ-JSOI2008最大数相关的知识,希望对你有一定的参考价值。

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;
 } 

以上是关于[线段树]校OJ-JSOI2008最大数的主要内容,如果未能解决你的问题,请参考以下文章

P1198 [JSOI2008]最大数 - 线段树

BZOJ1012: [JSOI2008]最大数maxnumber [线段树]

[BZOJ1012][JSOI2008]最大数maxnumber 线段树

[JSOI2008]最大数(线段树基础)

1012: [JSOI2008]最大数maxnumber 线段树

[JSOI2008]最大数maxnumber(线段树)