bzoj1012: [JSOI2008]最大数maxnumber(线段树+假装增点)

本文介绍了一种使用线段树解决特定问题的方法。通过构建一棵最多管理20万个点的线段树,并针对新增操作优化,实现了对区间最大值的有效查询。代码示例清晰展示了如何实现线段树的构建、更新及查询。

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

题目传送门

 这道题比裸的线段树难一丁点,注意题目:假装(连题目都要当戏精)

题目大意:

 1、给一棵空树:两个操作

2、A操作,在树的末尾(ed)增加一个点(值从上一次查询得来)

3、Q操作,求 (ed-L+1~ed)这个区间的max

4、值要用 龙龙(long long)

解题思路:

 1、题目很友(yin)善(hui)地说:操作数量不超过 20W,而且插入操作:每次只插入一个点。

 说人话:这棵树最多只管理20W个点,每次新增操作都是增一个点都在队尾!!

2、戏演完了:开一棵20W个点的空树,改点求段,毕。

3、别被 龙龙 坑了哦(反正我没有)

上代码(感觉没有写注解的必要):

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int mx=200005;

int lt=0;
struct nodt{int l,r,ls,rs;ll c;}t[mx*2];

void bt(int l,int r)
{
	lt++; int x=lt; t[x].l=l;t[x].r=r;t[x].c=0;
	int m=(l+r)/2;
	if(l<r)
	{
		t[x].ls=lt+1; bt(l,m);
		t[x].rs=lt+1; bt(m+1,r);
	}
}
ll fmax(int x,int l,int r)
{
	if(t[x].l==l && t[x].r==r) return t[x].c;
	int m=(t[x].l+t[x].r)/2,ls=t[x].ls,rs=t[x].rs;
	if(r<=m) return fmax(ls,l,r);
	else if(l>m) return fmax(rs,l,r);
	else return max(fmax(ls,l,m),fmax(rs,m+1,r));
}
void xg(int x,int y,ll k)
{
	if(t[x].l==t[x].r) { t[x].c=k; return ; }
	int m=(t[x].l+t[x].r)/2,ls=t[x].ls,rs=t[x].rs;
	if(y<=m) xg(ls,y,k);
	else xg(rs,y,k);
	t[x].c=max(t[ls].c,t[rs].c);
}
int main()
{	
	int n,ed=0; ll d,m=0,x;char s[10];
	
	scanf("%d %lld",&n,&d);
	
	bt(1,mx); 
	
	while(n--)
	{
		scanf("%s",s+1); scanf("%lld",&x);
		if(s[1]=='Q') 
		{
			printf("%lld\n",m=fmax(1,ed-x+1,ed));
		}
		else 
		{
			xg(1,++ed,(x+m)%d);
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值