CODEVS 1081 线段树练习 2

题目描述

给你N个数,有两种操作1:给区间[a,b]的所有数都增加X;2:询问第i个数是什么?

输入描述

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

输出描述

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

样例输入

3

1

2

3

2

1 2 3 2

2 3

样例输出

5

数据范围及提示

数据范围

1<=n<=100000

1<=q<=100000

解题思路:这道题目线段树模板,其中点查询用区间查询的方式。

#include <cstdio>  
#define ll long long  
using namespace std;  
struct TREE{  
    int l,r;
	ll sum,lazy;  
}tree[400005];  
int n,m,b,c,d,a[100005];  
inline int read()    
{    
    ll f=1,x=0;    
    char ch=getchar();    
    if (ch=='-')    
    {    
        f=-1;    
        ch=getchar();    
    }    
    while ((ch<'0')||(ch>'9')) ch=getchar();    
    while ((ch>='0')&&(ch<='9'))    
    {    
        x=x*10+ch-48;    
        ch=getchar();    
    }    
    return f*x;    
}    
inline void build(int root,int l,int r)  
{  
    tree[root].l=l;  
    tree[root].r=r;  
    if (l==r)  
    {  
        tree[root].sum=a[l];  
        return;  
    }  
    int mid=(l+r)/2;  
    build(root*2,l,mid);  
    build(root*2+1,mid+1,r);  
    tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;  
}  
inline void js(int root,int l,int r,int d)  
{  
    tree[root].lazy+=d;  
    tree[root].sum+=d*(r-l+1);  
}  
inline void push_down(int root,int l,int r)  
{  
    int mid=(l+r)/2;  
    js(root*2,l,mid,tree[root].lazy);  
    js(root*2+1,mid+1,r,tree[root].lazy);  
    tree[root].lazy=0;  
}  
inline void change(int root,int l,int r)  
{  
    int nl=tree[root].l,nr=tree[root].r;  
    int mid=(nl+nr)/2;  
    if ((l<=nl)&&(nr<=r))  
    {  
        tree[root].sum+=d*(nr-nl+1);  
        tree[root].lazy+=d;  
        return;  
    }  
    push_down(root,nl,nr);  
    if (l<=mid) change(root*2,l,r);  
    if (r>mid) change(root*2+1,l,r);  
    tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;  
}  
inline ll find(int root,int l,int r)
{
	int nl=tree[root].l,nr=tree[root].r;
	int mid=(nl+nr)/2;
	ll s=0;
	if ((l<=nl)&&(nr<=r)) return tree[root].sum;
	push_down(root,nl,nr);
	if (l<=mid) s+=find(root*2,l,r);  
    if (r>mid) s+=find(root*2+1,l,r);
    return s;
}
int main()  
{
    n=read();  
    for (int i=1;i<=n;i++) a[i]=read();  
    build(1,1,n);
    m=read();
    for (int i=1;i<=m;i++)  
    {  
        int x;  
        x=read();  
        if (x==1)  
        {  
            b=read(),c=read(),d=read();  
            change(1,b,c);  
        } else  
        {  
            b=read();
            printf("%lld\n",find(1,b,b));  
        }  
    }  
    return 0;  
}  


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值