首页 > 其他 > 详细

线段树-1081线段树练习

时间:2019-04-09 21:46:38      阅读:114      评论:0      收藏:0      [点我收藏+]

1081 线段树练习 2

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

给你N个数,有两种操作


1:给区间[a,b]的所有数都增加X


2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

数据范围

1<=n<=100000

1<=q<=100000

 

模板题

线段树就是二叉树加上一个迟缓标记,在进行区间修改的时候不直接修改整个区间的值,而是先对子树的根节点打上标记,标记可以累加,等到查询的时候再下放标记。

 

#include<bits/stdc++.h>
using namespace std;
const int MAXN=200005;
struct treeN{
    int val;
    int addM;//迟缓标记
}tree[MAXN*4];
int arr[MAXN];
void pushD(int root){//下移标记
    if(tree[root].addM){
        tree[root*2+1].addM+=tree[root].addM;
        tree[root*2+2].addM+=tree[root].addM;
        tree[root*2+1].val+=tree[root].addM;
        tree[root*2+2].val+=tree[root].addM;
    
        tree[root].addM=0;    
    }
}
int sum(int a,int b){
    return a+b;
}
void build(int root,int start,int end){
    tree[root].addM=0;
    if(start==end)
        tree[root].val=arr[start];
    else{
        int mid=(start+end)/2;
        build(root*2+1,start,mid);
        build(root*2+2,mid+1,end);
        
        tree[root].val=sum(tree[root*2+1].val,tree[root*2+2].val);
    }
}
int query(int root,int start,int end,int qstart,int qend){
    if(qstart>end||qend<start) return 0;
    
    if(qstart<=start&&qend>=end) return tree[root].val;
    
    pushD(root);
    int mid=(start+end)/2;
    return sum(query(root*2+1,start,mid,qstart,qend),query(root*2+2,mid+1,end,qstart,qend));
    
}

void update(int root,int start,int end,int index,int val){
    if(start==end){
        if(start==index) tree[root].val+=val;
        return ;
    }
    int mid=(start+end)/2;
    if(index<=mid)
        update(root*2+1,start,mid,index,val);
    else update(root*2+2,mid+1,end,index,val);
    tree[root].val=sum(tree[root*2+1].val,tree[root*2+2].val);
    
}

void updateD(int root,int start,int end,int qstart,int qend,int val){
    if(qstart>end||qend<start) return ;
    if(qstart<=start&&qend>=end){
        tree[root].addM+=val;
        tree[root].val+=val;
        return ;
    }
    pushD(root);
    int mid=(start+end)/2;
    updateD(root*2+1,start,mid,qstart,qend,val);
    updateD(root*2+2,mid+1,end,qstart,qend,val);
    tree[root].val=sum(tree[root*2+1].val,tree[root*2+2].val);
}
int main(){
    int n,i,j,x,y,m;
    cin>>n;
    for(i=0;i<n;i++) scanf("%d",&arr[i]);
    build(0,0,n-1);
    cin>>m;
    for(i=0;i<m;i++){
        scanf("%d",&j);
        if(j==1){
            scanf("%d%d%d",&x,&y,&j);
            updateD(0,0,n-1,x-1,y-1,j);
        }
        else{
            scanf("%d",&j);
            cout<<query(0,0,n-1,j-1,j-1)<<endl;
        }
        
    }
} 

 

 

线段树-1081线段树练习

原文:https://www.cnblogs.com/wengsy150943/p/10679762.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!