[算法设计与分析] 前缀和 (树状数组)

tag:树状数组,差分,前缀和

luogu P4868

&&学会使用class类简化代码就很奈斯

//
//  main.cpp
//  前缀和
//
//  Created by sylvia on 2021/10/25.
//  Copyright © 2021 apple. All rights reserved.
//
/*
 将ss展开可得ssi=(i+1)sigma(i,j=1)aj - sigma(i,j=1)j*aj
 所以可以维护两个树状数组sigma(i,j=1)aj  和sigma(i,j=1)j*aj
 第一个传统建树modify(i,a[i]) 单点修改modify(i,x-a[i])
 后者建树和单点修改为modify(i,a[i]*i) 和 modify(i,(x-a[i])*i)
 
 */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;

typedef long long ll;
const int MAXN=1e5+5;
ll n,m;
ll a[MAXN];
class BIT
{
private:
    ll tree[MAXN];
    ll lowbit(const ll x){return x&(-x);}
public:
    void modify(ll pos,const ll x)
    {
        for(;pos<=n;pos+=lowbit(pos))
         tree[pos]+=x;
    }
    ll query(ll pos)
    {
        ll res=0;
        for(;pos;pos-=lowbit(pos))
         res+=tree[pos];
        return res;
    }
}t1,t2;//简化代码

int main()
{
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
     cin>>a[i];
    for(ll i=1;i<=n;i++)
    {
        t1.modify(i,a[i]);
        t2.modify(i,a[i]*i);
    }
    while(m--)
    {
        string s;
        cin>>s;
        if(s=="Modify")
        {
            ll pos,x;
            cin>>pos>>x;
            t1.modify(pos,x-a[pos]);
            t2.modify(pos,(x-a[pos])*pos);
            a[pos]=x;
        }
        if(s=="Query")
        {
            ll pos;
            cin>>pos;
            cout<<((pos+1)*t1.query(pos)-t2.query(pos))<<endl;
        }
    }
    return 0;
}

 

posted @ 2021-10-26 16:37  Sylvia_lee  阅读(39)  评论(0编辑  收藏  举报