HDU 6315 G Naive Operations 线段树

这题看题面就知道是线段树了,但是我们发现 这个式子并不是很好维护,那么我们可以换一个思路,对于每个add操作,我们把B序列的对应区间-1,当B序列中某个位置上为0的时候,这个位置的答案就+1 并且把这个值又变回到Bi  这个很好理解 所以我们要维护区间的最小值来看-1后以后会不会有位置变成0   对于会变成0的位置我们需要单点更新 有些人可能觉得 如果有多个位置同时为1的话 复杂度会很高  其实不然 首先多个位置同时为1 需要很多次add操作 这一定程度上降低了query操作的次数 其次保证了效率的是 Bi是一个全排列 显然当为1的多个位置被更新后 又会变成完全不相同的数 可以保证复杂度(不会证明具体的复杂度)

#include<cstdio>
#include<cstring>
#include<algorithm> 
using namespace std;
const int N = 1e5+10;
typedef long long ll;
struct seg_tree{
	int l,r;
	ll sum,add,mi;
}T[N<<2];
ll b[N];
int n,q;
void pushup(int id){
	T[id].mi=min(T[id<<1].mi,T[id<<1|1].mi);
	T[id].sum=T[id<<1].sum+T[id<<1|1].sum;
}
void pushdown(int id){
	if(T[id].add){
		T[id<<1].mi+=T[id].add;
		T[id<<1|1].mi+=T[id].add;
		T[id<<1].add+=T[id].add;
		T[id<<1|1].add+=T[id].add;
		T[id].add=0; 
	}
}
void build(int id,int l,int r){
	T[id].l=l,T[id].r=r,T[id].add=T[id].sum=0;
	if(l==r){
		T[id].mi=1ll*b[l];
		return;
	} 
	int mid = l+r>>1;
	build(id<<1,l,mid);build(id<<1|1,mid+1,r);
	pushup(id);
}
void update(int id,int L,int R,ll val){
//	printf("T[id].l=%d T[id].r=%d\n",T[id].l,T[id].r);
	if(L<=T[id].l&&R>=T[id].r&&T[id].mi>1){
		T[id].add+=val;
		T[id].mi+=val;
		return;
	}
	if(T[id].l==T[id].r&&T[id].mi==1){
		T[id].add=0;
		T[id].sum++;
		T[id].mi=b[T[id].l];
		return;
	}
	pushdown(id);
	int mid = T[id].l+T[id].r>>1;
	if(L<=mid) update(id<<1,L,R,val);
	if(R>mid) update(id<<1|1,L,R,val);
	pushup(id); 
}
ll query(int id,int L,int R){
	if(L<=T[id].l&&R>=T[id].r){
		return T[id].sum;
	}
	ll ans = 0;
	int mid = T[id].l+T[id].r>>1;
	pushdown(id);
	if(L<=mid) ans+=query(id<<1,L,R);
	if(R>mid) ans+=query(id<<1|1,L,R);
	return ans;
}
void debug(int id){
	//printf("T[id].l=%d T[id].r=%d T[%d].add=%lld\n",T[id].l,T[id].r,id,T[id].add);
	if(T[id].l==T[id].r){
		return;
	}
	pushdown(id);
	int mid = T[id].l+T[id].r>>1;
	debug(id<<1);debug(id<<1|1);
}
int main(){
	while(~scanf("%d%d",&n,&q)){
		for(int i = 1; i <= n; i++) scanf("%lld",&b[i]);
		char s[10];
		int l,r;
		build(1,1,n);
		for(int i = 1; i <= q; i++){
			scanf("%s%d%d",s,&l,&r);
			if(s[0]=='a'){
				update(1,l,r,-1ll);
			}else{
				printf("%lld\n",query(1,l,r));
			}
			//debug(1);
		}
	}
	return 0;
}
/*
9 8
9 4 7 2 5 6 1 3 8 
a 1 9
a 1 2
q 1 3
q 4 7
a 1 4
a 1 1
q 3 7
q 1 4

*/
原创文章 85 获赞 103 访问量 2489

猜你喜欢

转载自blog.csdn.net/weixin_43824564/article/details/105794632