树状数组&线段树

A Simple Problem with Integers

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

树状数组

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N=100005;

int n, m;
int a[N];
LL tr1[N]; // 维护b[i]的前缀和
LL tr2[N]; // 维护b[i]*i的前缀和

int lowbit(int x){return x & -x;}
void add(LL tr[], int x, LL c){ // 更新树状数组
    for(int i=x; i<=n; i+=lowbit(i)) tr[i]+=c;
}
LL sum(LL tr[], int x){
    LL ans=0;
    for(int i=x; i; i-=lowbit(i)) ans+=tr[i];
    return ans;
}

LL prefix_sum(int x){
    return sum(tr1, x)*(x+1)-sum(tr2, x);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; ++i) scanf("%d", &a[i]);
    for(int i=1; i<=n; ++i){
        int b=a[i]-a[i-1];
        add(tr1, i, b);
        add(tr2, i, (LL)b*i);
    }
    while(m--){
        char ch[2];
        int l, r, d;
        scanf("%s%d%d", &ch, &l, &r);
        if(ch[0]=='Q'){
            printf("%lld\n", prefix_sum(r)-prefix_sum(l-1));
        }
        else{
            scanf("%d", &d);
            add(tr1, l, d);
            add(tr2, l, l*d);
            add(tr1, r+1, -d);
            add(tr2, r+1, (r+1)*(-d));
        }
    }

    return 0;
}

线段树(懒标记)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

typedef long long LL;
const int N=100005;
int n, m, a[N];
struct Node{
    int l, r;
    LL sum; // 存储总和
    LL tag; // 存储懒标记
}tr[N<<2];

inline void pushup(int u){tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;}
inline void pushdown(int u){
    Node &root =tr[u];
    Node &left=tr[u<<1];
    Node &right=tr[u<<1|1];
    if(root.tag){
        left.tag+=root.tag;
        left.sum+=(LL)(left.r-left.l+1)*root.tag;
        right.tag+=root.tag;
        right.sum+=(LL)(right.r-right.l+1)*root.tag;
        root.tag=0; // 父节点懒标记分解
    }
}

void build(int u, int l, int r){
    if(l==r) tr[u]={l, r, a[l], 0};
    else{
        tr[u]={l, r};
        int mid=l+r>>1;
        build(u<<1, l, mid);
        build(u<<1|1, mid+1, r);
        pushup(u);
    }
}

void modify(int u, int l, int r, int d){
    if(tr[u].l>=l && tr[u].r<=r){
        tr[u].sum+=(LL)(tr[u].r-tr[u].l+1)*d;
        tr[u].tag+=d;
    }
    else{
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) modify(u<<1, l, r, d);
        if(r>mid) modify(u<<1|1, l, r, d);
        pushup(u);
    }
}

LL query(int u, int l, int r){
    if(tr[u].l>=l && tr[u].r<=r) return tr[u].sum;
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    LL ans=0;
    if(l<=mid) ans+=query(u<<1, l, r);
    if(r>mid) ans+=query(u<<1|1, l, r);
    return ans;
}

int main(){
    cin>>n>>m;
    for(int i=1; i<=n; ++i) scanf("%d", &a[i]);
    build(1, 1, n);
    char op[2];
    int l, r, d;
    while(m--){
        scanf("%s%d%d", &op, &l, &r);
        if(op[0]=='C'){
            scanf("%d", &d);
            modify(1, l, r, d);
        }
        else cout<<query(1, l, r)<<endl;
    }
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务