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

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

下午敲了两遍直接就过了

嗯…重学线段树重新做人

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

___________________________________________________补记

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

空间*4

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

这样就有大量的空间浪费

为了避免这种空间浪费

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

有效的避免了浪费

所以空间开两倍即可

大概也算是dfs序吧

空间开两倍已检验 没有re

#include
#define maxn 100001
using namespace std;
template  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<


你可能感兴趣的:(caioj,线段树)