单点更新,区间求和

问题 M: 区间和

时间限制: 1 Sec  内存限制: 128 MB
提交: 11  解决: 5
[提交] [状态] [讨论版] [命题人:admin]
题目描述
给定一数列,规定有两种操作,一是修改某个元素,二是求区间的连续和。

 

输入
输入数据第一行包含两个正整数n,m(n<=100000,m<=500000),以下是m行,
每行有三个正整数k,a,b(k=0或1, a,b<=n).k=0时表示将a处数字加上b,k=1时表示询问区间[a,b]内所有数的和。

 

输出
对于每个询问输出对应的答案。

 

样例输入
10 20
0 1 10
1 1 4
0 6 6
1 4 10
1 8 9
1 4 9
0 10 2
1 1 8
0 2 10
1 3 9
0 7 8
0 3 10
0 1 1
1 3 8
1 6 9
0 5 5
1 1 8
0 4 2
1 2 8
0 1 1

 

样例输出
10
6
0
6
16
6
24
14
50
41

线段树和树状数组两种做法

线段树代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+10;
typedef long long ll;
struct node{
    int l,r,lazy;
    ll val;
}tr[maxn];
 
void Pushup(int i){
    tr[i].val=tr[i<<1].val+tr[i<<1|1].val;
}
void Pushdown(int i){
    if (tr[i].lazy){
        tr[i<<1].lazy+=tr[i].lazy;
        tr[i<<1|1].lazy+=tr[i].lazy;
        tr[i<<1].val+=1ll*(tr[i<<1].r-tr[i<<1].l+1)*tr[i].lazy;
        tr[i<<1|1].val+=1ll*(tr[i<<1|1].r-tr[i<<1|1].l+1)*tr[i].lazy;
        tr[i].lazy=0;
    }
}
void build(int l,int r,int i){
    tr[i].l=l,tr[i].r=r,tr[i].lazy=0;
    if(l==r) {
        tr[i].val=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    Pushup(i);
}
ll Query(int l,int r,int i){
    if(l<=tr[i].l && tr[i].r <=r) {
        return tr[i].val;
    }
    Pushdown(i);
    ll res=0;
    int mid=(tr[i].l+tr[i].r)>>1;
    if(l<=mid ) res+=Query(l,r,i<<1);
    if(r>mid) res+=Query(l,r,i<<1|1);
    return res;
}
void Update(int pos,int val,int i){
    if(tr[i].l==pos && tr[i].r ==pos){
        tr[i].val+=1ll*(tr[i].r-tr[i].l+1)*val;
        tr[i].lazy+=val;
        return ;
    }
    Pushdown(i);
    int mid=(tr[i].l+tr[i].r)>>1;
    if(pos<=mid) Update(pos,val,i<<1);
    else Update(pos,val,i<<1|1);
    Pushup(i);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    for (int op,a,b,i=1; i<=m; i++){
        scanf("%d",&op);
        scanf("%d%d",&a,&b);
        if(!op) Update(a,b,1);
        else printf("%lld\n",Query(a,b,1));
    }
    return 0;
}

 


树状数组做法:
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+10;
typedef long long ll;
ll tree[maxn],n,m;
inline int lowbit(int x){return x&-x;}
inline void Update(int x,int val){ for (int i=x; i<=n; i+=lowbit(i)) tree[i]+=val; }
inline ll Query(int x){
    ll res=0;
    for (int i=x; i; i-=lowbit(i)) res+=tree[i];
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int op,a,b,i=1; i<=m; i++){
        scanf("%d",&op);
        scanf("%d%d",&a,&b);
        if(!op) Update(a,b);
        else printf("%lld\n",Query(b)-Query(a-1));
    }
    return 0;
}

 

 

 

转载于:https://www.cnblogs.com/acerkoo/p/9495484.html

树状数组(Fenwick Tree)是一种用于高效处理区间修改和单点查询的数据结构。下面我将介绍如何使用树状数组实现区间修改和单点查询。 首先,我们需要定义树状数组的数据结构。树状数组由一个数组和一组操作组成,其中数组用于存储数据,操作用于更新和查询数组中的值。 下面是一个示例的树状数组实现: ```python class FenwickTree: def __init__(self, n): self.size = n self.tree = [0] * (n + 1) def update(self, idx, delta): while idx <= self.size: self.tree[idx] += delta idx += idx & -idx def query(self, idx): res = 0 while idx > 0: res += self.tree[idx] idx -= idx & -idx return res def range_update(self, l, r, delta): self.update(l, delta) self.update(r + 1, -delta) def point_query(self, idx): return self.query(idx) ``` 在上面的代码中,我们定义了一个FenwickTree类,通过构造函数`__init__`来初始化树状数组,并使用`size`来表示数组的大小。`tree`数组用于存储数据。`update`方法用于更新指定位置的值,`query`方法用于查询指定位置之前的求和结果。`range_update`方法用于对指定区间进行修改,`point_query`方法用于查询单个位置的值。 下面是一个示例的使用场景: ```python # 示例使用 n = 10 tree = FenwickTree(n) # 区间修改 [2, 6] 的值加 3 tree.range_update(2, 6, 3) # 查询位置 5 的值 value = tree.point_query(5) print(value) ``` 在上面的示例中,我们创建了一个大小为10的树状数组,并对区间[2, 6]的值进行了修改,将其加3。然后,我们查询了位置5的值,结果为3。 希望以上内容能够帮助到你实现树状数组的区间修改和单点查询。如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值