zoukankan      html  css  js  c++  java
  • [模板]线段树

    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
    ",ask_sum(1,a,b));
    		}
    		else if(s == "max"){
    			scanf("%d%d",&a,&b);
    			printf("%d
    ",ask_max(1,a,b));
    		}
    		else if(s == "min"){
    			scanf("%d%d",&a,&b);
    			printf("%d
    ",ask_min(1,a,b));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    通过引入SiteMesh的JSP标签库,解决Freemarker与SiteMesh整合时,自定义SiteMesh标签的问题
    我为什么要写FansUnion个人官网-BriefCMS-电子商务malling等系统
    我为什么要写FansUnion个人官网-BriefCMS-电子商务malling等系统
    天龙八部回归记
    天龙八部回归记
    到底要不要买彩票,纠结了
    到底要不要买彩票,纠结了
    与Boss大雷探讨JavaWeb开发、电商与网络安全
    与Boss大雷探讨JavaWeb开发、电商与网络安全
    Fiori里花瓣的动画效果实现原理
  • 原文地址:https://www.cnblogs.com/loi-pingxing/p/7808339.html
Copyright © 2011-2022 走看看