洛谷 P5889 跳树

大体思路很简单,用线段树维护区间操作,询问便是区间查询即可

真正有难度的地方在于操作区间合并,比较难理解。

注意,代码中写的运算符重载只能运用于先进行的操作+后进行的操作

操作区间合并对我这样的蒟蒻还是挺难理解的

sys orz.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=5e5+10;
int n,m,q;
int max(int a,int b){
    if(a>b)
        return a;
    else
        return b;
}
int p[maxn];
struct node{
	int fm;
	int l;
	int num;
}tre[maxn*5];
int k;
node operator + (node x,node y){
	node ans=(node){0,0,0};
	if(!x.fm&&!x.l){
		return y;
	}
	if(!y.fm&&!y.l){
		return x;
	}
	if(x.l>y.fm){
		ans.fm=x.fm;
		ans.l=x.l-y.fm+y.l;
		ans.num=((x.num>>y.fm)<<y.l)+y.num;
	} 
	else{
		ans.fm=x.fm+y.fm-x.l;
		ans.l=y.l;
		ans.num=y.num;
	}
	return ans;
}
void build(int rt,int l,int r){
	if(l==r){
		cin>>k;
		if(k==1){
			tre[rt].l=1;
		}
		else if(k==2){
			tre[rt].l=1;
			tre[rt].num=1;
		}	
		else if(k==3){
			tre[rt].fm=1;
		}
		return ;
	}
	int mid=(l+r)>>1;
	build(rt*2,l,mid);
	build(rt*2+1,mid+1,r);
	tre[rt]=tre[rt*2]+tre[rt*2+1];
	return ;
}
node query(int rt,int l,int r,int ql,int qr){
	node ans=(node){0,0,0};
	if(r<ql||l>qr){
		return ans;
	}
	if(l>=ql&&r<=qr){
		return tre[rt];
	}
	int mid=(l+r)>>1;
	if(ql<=mid){
		ans=ans+query(rt*2,l,mid,ql,qr);
	}
	if(qr>mid){
		ans=ans+query(rt*2+1,mid+1,r,ql,qr);
	}
	return ans;
}
void update(int rt,int l,int r,int pos,int x){//??
    if(l==r){
        tre[rt]=(node){0,0,0};
        if(x==1){
            tre[rt].l=1;
        }
        else if(x==2){
            tre[rt].l=1;
            tre[rt].num=1;
        }
        else{
            tre[rt].fm=1;
        }
        return;
    }
    int mid=(l+r)>>1;
    if(pos>mid){
        update(rt*2+1,mid+1,r,pos,x);
    }
    else{
        update(rt*2,l,mid,pos,x);
    }
    tre[rt]=tre[rt*2]+tre[rt*2+1];
}
signed main(){
//	freopen("a.in","r",stdin);
	cin>>n>>m>>q;
	//cout<<n<<m<<q;
	build(1,1,m);
	int t;
	node x;
	while(q--){
		cin>>t;
		if(t==1){
			int ll,rr,s;
			cin>>s>>ll>>rr;
			x=query(1,1,m,ll,rr);
	//		cout<<x.fm<<" "<<x.l<<" "<<x.num<<endl;
			cout<<((max(1,s>>x.fm))<<x.l)+x.num<<endl;	
		}
		if(t==2){
			int d,y;
			cin>>d>>y;
			update(1,1,m,d,y);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/rpup/p/13903556.html