• A A Simple Problem with Integers (线段树的区间修改与区间查询)


    You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15
    代码如下
    #include
    #include
    typedef long long ll;
    const int N=1e5+7;
    int n,q;
    int a[N];
    struct node{  //建树 
    	int l,r,len;//多了一个区间长度len和懒标记 
    	ll sum,lazy;
    }tree[N*4];
    void pushup(int now){//向上更新sum 
    	tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
    }
    void buildtree(int now, int l,int r){
    	tree[now].l=l;
    	tree[now].r=r;
    	tree[now].lazy=0;// 建树时懒标记置零 
    	tree[now].len=r-l+1;
    	if(l==r){
    		tree[now].sum=a[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	buildtree(now<<1,l,mid);
    	buildtree(now<<1|1,mid+1,r);
    	pushup(now);
    } 
    void pushdown(int now){ //向子孙传递懒标记 
    	if(tree[now].lazy){
    		tree[now<<1].sum+=tree[now].lazy*tree[now<<1].len;
    		tree[now<<1].lazy+=tree[now].lazy;
    		tree[now<<1|1].sum+=tree[now].lazy*tree[now<<1|1].len;
    		tree[now<<1|1].lazy+=tree[now].lazy;
    		tree[now].lazy=0;
    	}
    }
    void add(int now,int l,int r,int v){
    	int L=tree[now].l,R=tree[now].r;
    	if(l<=L&&R<=r){//如果现区间已经完全在所要修改的区间以内,则不需要继续向下修改,进行懒标记就好 
    		tree[now].sum+=tree[now].len*v;
    		tree[now].lazy+=v;
    		return;
    	}
    	pushdown(now);//懒标记由父辈传给子辈 
    	int mid=(L+R)>>1;
    	if(mid>=l)add(now<<1,l,r,v);//与左儿子有交集 
    	if(mid<r)add(now<<1|1,l,r,v);//与右儿子有交集 
    	pushup(now);
    }
    ll query(int now,int l,int r){
    	int L=tree[now].l,R=tree[now].r;
    	if(l==L&&r==R)return tree[now].sum;//现区间的边界与需要查询的边界刚刚好相同直接返回 
    	pushdown(now);//真正懒的所在,需要用到的时候懒标记才会继续向下传递,add里面并没有将子孙更新完全 
    	int mid=(L+R)>>1;
    	if(l>mid)return query(now<<1|1,l,r);
    	else if(r<=mid)return query(now<<1,l,r);
    	else return query(now<<1,l,mid)+query(now<<1|1,mid+1,r);
    }
    int main(){
    	scanf("%d%d",&n,&q);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	buildtree(1,1,n);
    	while(q--){
    		char str[3];
    		scanf("%s",str);
    		if(str[0]=='C'){
    			int x,y,v;
    			scanf("%d%d%d",&x,&y,&v);
    			add(1,x,y,v);
    		}
    		else{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			printf("%lld\n",query(1,x,y));
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    fiddler配置及使用教程
    AcWing 刷题1
    王文 《深水炸弹》(二)关于我纯文学启蒙的一篇文章
    C++用法个人速记
    Acwing 刷题3
    AcWing 刷题2
    王文《深水炸弹》(一)关于我纯文学启蒙的一篇文章
    Acwing 刷题4
    MySQL主从复制断开恢复过程
    Zookeeper集群部署及给dubbo节点加auth认证
  • 原文地址:https://www.cnblogs.com/chuliyou/p/12533523.html
Copyright © 2020-2023  润新知