codevs 1081 线段树练习 2

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

代码一:

codevs 1081
#include<cstdio>
#include<iostream>

using namespace std;
int n,m;
int sz[100010];
struct node
{
    int val,delta,l,r;
    node * cl,*cr;
 }* root=NULL;
int sv(node * cur)
{
    return cur?cur->val:0;
}
void down(node * cur)
{
    if(cur->cl)
    {
        cur->cl->delta+=cur->delta;
        cur->cl->val+=cur->delta*(cur->cl->r-cur->cl->l+1);//叶节点是有用的,其余的区间是没用的 
    }
    if(cur->cr)
    {
        cur->cr->delta+=cur->delta;
        cur->cr->val+=cur->delta*(cur->cr->r-cur->cr->l+1);
    }
    cur->delta=0;
}
void build(node * &cur,int l,int r)
{
    if(r<l)return;
    cur=new node;
    cur->l=l;cur->r=r;cur->delta=0;
    if(l==r)
    {
        cur->val=sz[l];
        cur->cl=cur->cr=NULL;
    }
    
    else
    {
        int mid=(l+r)/2;
        build(cur->cl,l,mid);
        build(cur->cr,mid+1,r);
        //不用更新当前的val,因为题目中没说要求区间的值 
    }
}

int query(node * cur,int pos)
{
    if(cur->l==cur->r)return cur->val;
    if(cur->delta)down(cur);/**/
    int mid=(cur->l+cur->r)/2; 
    if(pos<=mid)return query(cur->cl,pos);/*一定是return,,否则就从最里面返回一个数,不会返回到主函数*/ 
    else return query(cur->cr,pos);
}
void add(node * cur,int l,int r,int delta)
{
    if(l<=cur->l&&cur->r<=r)
    {
        cur->delta+=delta;/*记录当前区间欠这个区间内的每个数多少*/ 
        cur->val+=delta;//当cur是叶节点时,有用 
        return;
    }
    int mid=(cur->l+cur->r)/2;
    if(cur->delta)down(cur);/*如果要取这个区间的一部分加上delta的话,先把这个区间欠下面的数传下去,而不是先加上delta,因为这样直接加会把区间的其他部分多加了delta*/
    if(l<=mid)add(cur->cl,l,r,delta);
    if(mid<r)add(cur->cr,l,r,delta);
}
int main()
{
    cin>>n;
    for(int j=1;j<=n;j++)scanf("%d",&sz[j]);
    build(root,1,n);
    cin>>m;
    for(int i=0;i<m;i++)
    {
        int a,b,c,d;
        scanf("%d",&a);
        if(a==1)
        {
            scanf("%d%d%d",&b,&c,&d);
            add(root,b,c,d);
        }
        else if(a==2)
        {
            scanf("%d",&b);
            printf("%d
",query(root,b));
        }
    }
    return 0;
}
teacher's

代码二:

#include<cstdio> 
#include<iostream>
using namespace std;
#define INF 100001
int sz[INF];
struct node {
    int l,r,delta;
    node *child[2];
    int val;
}*root=NULL;
int n,q,a,b,c,x;
void input()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    scanf("%d",&sz[i]);
}
void update(node *cur)
{
    cur->val=cur->child[0]->val+cur->child[1]->val;
}
void bulid(node *&cur,int l,int r)
{
    if(l>r) return ;
    cur=new node;
    cur->l=l;cur->r=r;
    cur->delta=0;
    if(l==r)
    {
        cur->child[0]=cur->child[1]=NULL;
        cur->val=sz[l];
    }
    else {
        int mid=(l+r)/2;
        bulid(cur->child[0],l,mid);
        bulid(cur->child[1],mid+1,r);
    //    update(cur);
    }
}
void down(node * cur)
{
    if(cur->child[0])
    {
        cur->child[0]->delta+=cur->delta;
        cur->child[0]->val+=cur->delta*(cur->child[0]->r-cur->child[0]->l+1);
    }
    if(cur->child[1])
    {
        cur->child[1]->delta+=cur->delta;
        cur->child[1]->val+=cur->delta*(cur->child[1]->r-cur->child[1]->l+1);
    }
    cur->delta=0;
}
void add(node* cur,int l,int r,int delta)
{
    if(cur->l>=l&&cur->r<=r)
    {
        cur->delta+=delta;
        cur->val+=delta*(cur->l-cur->r+1);
        return ;
    }
    int mid=(cur->l+cur->r)/2;
    if(cur->delta) down(cur);
    if(l<=mid) add(cur->child[0],l,r,delta);
    if(r>mid) add(cur->child[1],l,r,delta);
}
int query(node* cur,int x)
{
    if(cur->l==cur->r)
    {
        return cur->val;
    }
    if(cur->delta) down(cur);
    int mid=(cur->l+cur->r)/2;
    if(x<=mid) return query(cur->child[0],x);
    else return query(cur->child[1],x);
}
int main()
{
    input();
    bulid(root,1,n);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&x);
        if(x==1){
            scanf("%d%d%d",&a,&b,&c);
            add(root,a,b,c);
        } 
        else {
            scanf("%d",&a);
            printf("%d
",query(root,a));
        }
    }
    return 0;
}
mine
原文地址:https://www.cnblogs.com/c1299401227/p/5318221.html