caioj1099 线段树(区间修改+求区间最大值

打模拟赛前写了很多次都不能过

下午敲了两遍直接就过了

嗯…重学线段树重新做人

还是比较后悔上午的暴力分没拿全

___________________________________________________补记

看了一下别的版本的线段树

空间*4

是因为通过2*n 和2*n+1来存储子节点

这样就有大量的空间浪费

为了避免这种空间浪费

caioj上这种写法 另外申请了lc rc两个数组

有效的避免了浪费

所以空间开两倍即可

大概也算是dfs序吧

空间开两倍已检验 没有re

#include<bits/stdc++.h>
#define maxn 100001
using namespace std;
template <typename T> void read(T &x){
	x=0;int f=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
	for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+ch-'0';
	x*=f;
}

int n,m;
int a[maxn];
struct node{
	int l,r,lc,rc,maxc;
}tr[maxn*2];int len;

void bt(int l,int r){
	++len;int now=len;
	tr[now].l=l,tr[now].r=r;
	tr[now].lc=tr[now].rc=-1;
	if(l==r) tr[now].maxc=a[l];
	else{
		int mid=(l+r)>>1;
		tr[now].lc=len+1,bt(l,mid);
		tr[now].rc=len+1,bt(mid+1,r);
		tr[now].maxc=max(tr[tr[now].lc].maxc,tr[tr[now].rc].maxc);
	}
}

void changed(int now,int x,int k){
	if(tr[now].l==tr[now].r){
		tr[now].maxc=k;
		return;
	}
	int lc=tr[now].lc,rc=tr[now].rc;
	int mid=(tr[now].l+tr[now].r)>>1;
	if(x<=mid) changed(lc,x,k);
	else if(x>=mid+1) changed(rc,x,k);
	tr[now].maxc=max(tr[lc].maxc,tr[rc].maxc);
}

int findmax(int now,int l,int r){
	if(l==tr[now].l&&r==tr[now].r) return tr[now].maxc;
	int lc=tr[now].lc,rc=tr[now].rc;
	int mid=(tr[now].l+tr[now].r)>>1;
	if(r<=mid) findmax(lc,l,r);
	else if(l>=mid+1) findmax(rc,l,r);
		 else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}

int main(){
	read(n),read(m);
	for(int i=1;i<=n;++i) read(a[i]);
	bt(1,n);
	for(int i=1;i<=m;++i){
		string a;int x,y;
		cin>>a;
		read(x),read(y);
		if(a[0]=='C') changed(1,x,y);
		else{
			if(x>y) swap(x,y);
			cout<<findmax(1,x,y)<<endl;
		}
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值