hdu1166_敌兵布阵(线段树入门)


///
作者:tt2767
声明:本文遵循以下协议自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0
查看本文更新与讨论请点击:http://blog.csdn.net/tt2767
链接被删请百度: CSDN tt2767
///


简单线段树求动态区间和

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166

#include<string>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define lch(x)  ((x) << 1)
#define rch(x) ((x)<<1|1)
#define dad(x) ((x)>>1)

typedef  long long int LL;
const int N = 10 + 1000000;
int sum[N];

void build(int l,int r,int rt);
void updata(int mark,int val ,int l,int r,int rt);
int query(int x,int y ,int l ,int r ,int rt)  ;
void pushup(int rt);

int main()
{
    int Case, tot = 1;
    scanf("%d", &Case);
    while(Case--)
    {
        printf("Case %d:\n", tot++);
        int n;
        scanf("%d", &n);
        build(1,n,1);

        char q[10];
        while (scanf("%s", q) ==1&& q[0] != 'E')
        {
            int x, y;
            scanf("%d%d", &x, &y);

            if (q[0] == 'Q')
                printf("%d\n", query(x, y, 1, n, 1));
            else if (q[0] == 'S')
                updata(x, -y, 1, n, 1);
            else
                updata(x, y, 1, n, 1);
        }
    }
    return 0;
}

void pushup(int rt)
{
        sum[rt] = sum[lch(rt)] + sum[rch(rt)]; //父节点的值为左右儿子之和
                                            //虽然只更新了一边,但下边代码保证每个值都更新过
}
void build(int l,int r,int rt)
{
    if (l == r)
    {
        scanf("%d",&sum[rt]);       //当区间小到一个点的时候为它赋值
        return;
    }
    int mid = (r+l) >>1;
    build(l,mid,lch(rt) );       //递归建树
    build(mid +1,r,rch(rt));
    pushup(rt);         //每次从底向上为父节点求值
}

void updata(int mark,int val ,int l,int r,int rt)
{
    if(l == r)
    {
        sum[rt] += val;//范围精确到一个点的时候更新它
    }
    else
    {
        int mid  = (l+r)>>1;
        if(mark <= mid) updata(mark,val,l,mid,lch(rt));
        else                updata(mark,val,mid+1,r,rch(rt));
        pushup(rt); //更新父节点的值
    }

}

int query(int x,int y ,int l ,int r ,int rt)
{
    if(x <= l && r <= y)
        return sum[rt]; //已经找到被查询的范围返回
    int ans = 0;
    int mid  = (l+r)>>1;
    if(x <= mid)  ans += query(x,y,l,mid, lch(rt));
    if( mid < y) ans+= query(x,y,mid+1,r ,rch(rt));
    return ans;          //所有分区间的组合就是最终结果
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值