题解 | #Big Water Problem#

Big Water Problem

https://ac.nowcoder.com/acm/problem/15164

思路

看数据范围1e5,暴力求和会被查询卡掉,用前缀和会被单点修改卡掉,所以我们要用到线段树。
线段树(查询+单点修改),背板代码如下。
我的码风把int定义成ll了,希望你们看的习惯。

代码

#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
const int maxn=100005;
int n,m,f,x,y,a[maxn],tree[maxn*4];

void build(int node,int start,int end){
    if(start==end){
        tree[node]=a[start];
        return;
    }
    int mid=start+end>>1;
    build(node<<1,start,mid);
    build(node<<1|1,mid+1,end);
    tree[node]=tree[node<<1]+tree[node<<1|1];
}

void add(int node,int start,int end,int num,int val){
    if(start==end){
        tree[node]=val;
        a[num]=val;
        return;
    }
    int mid=start+end>>1;
    if(num<=mid) add(node<<1,start,mid,num,val);
    if(num>mid) add(node<<1|1,mid+1,end,num,val);
    tree[node]=tree[node<<1]+tree[node<<1|1];
}

int query(int node,int start,int end,int l,int r){
    if(l<=start&&end<=r) return tree[node];
    int mid=start+end>>1;
    int res=0;
    if(l<=mid) res+=query(node<<1,start,mid,l,r);
    if(r>mid) res+=query(node<<1|1,mid+1,end,l,r);
    return res; 
}

signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)    scanf("%lld",&a[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&f,&x,&y);
        if(f==1) add(1,1,n,x,a[x]+y);
        else if(f==2) cout<<query(1,1,n,x,y)<<endl;
    }
    return 0;
}
全部评论
其实这道题用树状数组或者是直接模拟还更好一点,毕竟线段树真的太麻烦了
点赞 回复 分享
发布于 2023-08-04 20:48 江西

相关推荐

01-14 16:23
广州商学院 Java
双非后端失败第N人:如果准备好了可以直接投字节,字节是最不看学历的,只要想面,大概率都能给你约面。
双非有机会进大厂吗
点赞 评论 收藏
分享
评论
2
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务