[模板]线段树

codevs4927

1、注意代码是左闭右闭的线段树,mid在左区间内
2、打权值线段树时注意线段树右端点大于最大值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define L(w) w << 1
#define R(w) w << 1|1
#define INF 1061109567
typedef long long LL;
using namespace std;
const int MAXN = 200000 + 50;
int L[MAXN << 2],R[MAXN << 2],maxn[MAXN << 2],minx[MAXN << 2],M1[MAXN << 2],M2[MAXN << 2];
LL sum[MAXN << 2];
int A[MAXN];
void update(int w){
	sum[w] = sum[L(w)] + sum[R(w)];
	minx[w] = min(minx[L(w)],minx[R(w)]);
	maxn[w] = max(maxn[L(w)],maxn[R(w)]);
}
void spread1(int w){
	if(M1[w] == -1)return;
	int m = M1[w];
	M1[w] = -1;
	minx[L(w)] = maxn[L(w)] = m;
	minx[R(w)] = maxn[R(w)] = m;
	sum[L(w)] = m*(R[L(w)] - L[L(w)] + 1);
	sum[R(w)] = m*(R[R(w)] - L[R(w)] + 1);
	M2[L(w)] = M2[R(w)] = 0;
	M1[L(w)] = M1[R(w)] = m;
}
void spread(int w){
	if(M1[w] != -1){
		spread1(w);
	}
	int m = M2[w];
	if(!m)return;
	M2[w] = 0;
	spread1(L(w));
	spread1(R(w));
	maxn[L(w)] += m;
	maxn[R(w)] += m;
	minx[L(w)] += m;
	minx[R(w)] += m;
	sum[L(w)] += m*(R[L(w)] - L[L(w)] + 1);
	sum[R(w)] += m*(R[R(w)] - L[R(w)] + 1);
	M2[L(w)] += m;
	M2[R(w)] += m;
}
void build(int w,int l,int r){
	L[w] = l;R[w] = r;
	if(l == r){
		sum[w] = minx[w] = maxn[w] = A[l];
		return;
	}
	int mid = l + r >> 1;
	build(L(w),l,mid);
	build(R(w),mid + 1,r);
	update(w);
}
void cover(int w,int l,int r,int v){
	if(L[w] == l && R[w] == r){
		M2[w] = 0;
		M1[w] = v;
		minx[w] = maxn[w] = v;
		sum[w] = v*(R[w] - L[w] + 1);
		return;
	}
	spread(w);//重置前,先下放标记 
	int mid = L[w] + R[w] >> 1;
	if(r <= mid)cover(L(w),l,r,v);
	else if(l > mid)cover(R(w),l,r,v);
	else cover(L(w),l,mid,v),cover(R(w),mid + 1,r,v);
	update(w);
}
void add(int w,int l,int r,int v){
	if(L[w] == l && R[w] == r){
		spread1(w);
		M2[w] += v;
		minx[w] += v;
		maxn[w] += v;
		sum[w] += v*(R[w] - L[w] + 1);
		return;
	}
	spread(w);
	int mid = L[w] + R[w] >> 1;
	if(r <= mid)add(L(w),l,r,v);
	else if(l > mid)add(R(w),l,r,v);
	else add(L(w),l,mid,v),add(R(w),mid + 1,r,v);
	update(w);
}
LL ask_sum(int w,int l,int r){
	if(L[w] == l && R[w] == r){
		return sum[w];
	}
	spread(w);
	LL ans = 0;
	int mid = L[w] + R[w] >> 1;
	if(r <= mid)ans = ask_sum(L(w),l,r);
	else if(l > mid)ans = ask_sum(R(w),l,r);
	else ans = ask_sum(L(w),l,mid) + ask_sum(R(w),mid + 1,r);
	return ans;
}
int ask_max(int w,int l,int r){
	if(L[w] == l && R[w] == r){
		return maxn[w];
	}
	spread(w);
	int mid = L[w] + R[w] >> 1;
	int ans = -INF;
	if(r <= mid)ans = ask_max(L(w),l,r);
	else if(l > mid)ans = ask_max(R(w),l,r);
	else ans = max(ask_max(L(w),l,mid),ask_max(R(w),mid + 1,r));
	return ans;
}
int ask_min(int w,int l,int r){
	if(L[w] == l && R[w] == r){
		return minx[w];
	}
	spread(w);
	int mid = L[w] + R[w] >> 1;
	int ans = INF;
	if(r <= mid)ans = ask_min(L(w),l,r);
	else if(l > mid)ans = ask_min(R(w),l,r);
	else ans = min(ask_min(L(w),l,mid),ask_min(R(w),mid + 1,r));
	return ans;
}
int n,m,a,b,c;
string s;
int main(){
	memset(M1,-1,sizeof(M1));
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i ++){
		scanf("%d",&A[i]);
	}
	build(1,1,n);
	for(int i = 1;i <= m;i ++){
		cin >> s;
		if(s == "add"){
			scanf("%d%d%d",&a,&b,&c);
			add(1,a,b,c);
		}
		else if(s == "set"){
			scanf("%d%d%d",&a,&b,&c);
			cover(1,a,b,c);
		}
		else if(s == "sum"){
			scanf("%d%d",&a,&b);
			if(a > b)swap(a,b);
			printf("%lld\n",ask_sum(1,a,b));
		}
		else if(s == "max"){
			scanf("%d%d",&a,&b);
			printf("%d\n",ask_max(1,a,b));
		}
		else if(s == "min"){
			scanf("%d%d",&a,&b);
			printf("%d\n",ask_min(1,a,b));
		}
	}
	return 0;
}
posted @ 2017-11-09 10:58  _平行  阅读(146)  评论(0编辑  收藏  举报