• 【模板】线段树 区间修改+区间查询


    题目大意:维护一个长度为 N 的序列,支持区间修改、区间查询两种操作。

    update on 2019.4.3
    线段树分为指针式线段树和堆式线段树。指针式线段树的优点是空间较小,可以进行可持久化操作。堆式线段树的优点是可以不必记录左右儿子,缺点是区间要开到四倍,且不能可持久化,不过对于树套树的外层线段树来说,采用堆式线段树看起来更加直观。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    
    int n,m;
    long long a[maxn];
    
    struct node{
    	#define ls(x) t[x].lc
    	#define rs(x) t[x].rc
    	int lc,rc;
    	long long sum,tag;
    }t[maxn<<1];
    int tot,root;
    inline void pushup(int x){
    	t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
    }
    inline void pushdown(int x,int l,int r){
    	int mid=l+r>>1;
    	t[ls(x)].sum+=(mid-l+1)*t[x].tag,t[ls(x)].tag+=t[x].tag;
    	t[rs(x)].sum+=(r-mid)*t[x].tag,t[rs(x)].tag+=t[x].tag;
    	t[x].tag=0;
    }
    int build(int l,int r){
    	int x=++tot;
    	if(l==r){t[x].sum=a[l];return x;}
    	int mid=l+r>>1;
    	ls(x)=build(l,mid),rs(x)=build(mid+1,r);
    	pushup(x);
    	return x;
    }
    void modify(int o,int l,int r,int x,int y,long long val){
    	if(l==x&&r==y){t[o].sum+=(r-l+1)*val,t[o].tag+=val;return;}
    	int mid=l+r>>1;
    	pushdown(o,l,r);
    	if(y<=mid)modify(ls(o),l,mid,x,y,val);
    	else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
    	else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
    	pushup(o);
    }
    long long query(int o,int l,int r,int x,int y){
    	if(l==x&&r==y)return t[o].sum;
    	int mid=l+r>>1;
    	pushdown(o,l,r);
    	if(y<=mid)return query(ls(o),l,mid,x,y);
    	else if(x>mid)return query(rs(o),mid+1,r,x,y);
    	else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
    }
    void read_and_parse(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    	root=build(1,n);
    }
    
    void solve(){
    	while(m--){
    		int opt,val,l,r;
    		scanf("%d",&opt);
    		if(opt==1){
    			scanf("%d%d%d",&l,&r,&val);
    			modify(root,1,n,l,r,val);
    		}else{
    			scanf("%d%d",&l,&r);
    			printf("%lld
    ",query(root,1,n,l,r));
    		}
    	}
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=1e6+10;
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    int n,m,a[maxn];
    #define ls(o) o<<1
    #define rs(o) o<<1|1
    struct node{ll sum,tag;}t[maxn<<2];
    inline void pushup(int o){t[o].sum=t[ls(o)].sum+t[rs(o)].sum;}
    inline void pushdown(int o,int l,int r){
    	int mid=l+r>>1;
    	t[ls(o)].sum+=t[o].tag*(mid-l+1),t[ls(o)].tag+=t[o].tag;
    	t[rs(o)].sum+=t[o].tag*(r-mid),t[rs(o)].tag+=t[o].tag;
    	t[o].tag=0;
    }
    void build(int o,int l,int r){
    	if(l==r){t[o].sum=a[l];return;}
    	int mid=l+r>>1;
    	build(ls(o),l,mid),build(rs(o),mid+1,r);
    	pushup(o);
    }
    void modify(int o,int l,int r,int x,int y,ll val){
    	if(l==x&&r==y){t[o].sum+=val*(r-l+1),t[o].tag+=val;return;}
    	int mid=l+r>>1;
    	pushdown(o,l,r);
    	if(y<=mid)modify(ls(o),l,mid,x,y,val);
    	else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
    	else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
    	pushup(o);
    }
    ll query(int o,int l,int r,int x,int y){
    	if(l==x&&r==y)return t[o].sum;
    	int mid=l+r>>1;
    	pushdown(o,l,r);
    	if(y<=mid)return query(ls(o),l,mid,x,y);
    	else if(x>mid)return query(rs(o),mid+1,r,x,y);
    	else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
    }
    
    void read_and_parse(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	build(1,1,n);
    }
    
    void solve(){
    	while(m--){
    		int opt=read();
    		if(opt==1){
    			int l=read(),r=read(),x=read();
    			modify(1,1,n,l,r,x);
    		}else{
    			int l=read(),r=read();
    			printf("%lld
    ",query(1,1,n,l,r));
    		}
    	}
    }
    
    int main(){
    	//freopen("D:\学习\Code\对拍\data.in");
    	//freopen("D:\学习\Code\对拍\test.out");
    	read_and_parse();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    sqlserver中递归写法
    keytools命令生成证书
    java中sql语句快速处理
    select * 替换写法
    oracle行转列
    oracle中查看当前用户的表结构、主键、索引
    Servlet三种实现方式
    【python之旅】python的面向对象
    【python之旅】python的模块
    【python之旅】python的基础三
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9976731.html
Copyright © 2020-2023  润新知