树状数组笔记

lowbit:保留数在2进制下最后一个1,前面全变0

模板1:单点修改,区间查询

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n[500009];
int t,k;
int lowbit(int m)
{
    return m&-m;
}
void cr(int i,int x) 
{
    while(i<=t)
    {
        n[i]+=x;
        i+=lowbit(i);
    }
}
int show(int i)
{
    int ans=0;
    while(i!=0)
    {
        ans+=n[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    cin>>t>>k;
    for(int i=1;i<=t;i++)
    {
        int a;
        cin>>a;
        cr(i,a);
    }
    while(k--)
    {
        int a,b,c;cin>>a>>b>>c;
        if(a==1)
        cr(b,c);
        else if(a==2)
        cout<<show(c)-show(b-1)<<endl;
    }
    return 0;
}

 

例题:Problem - 1679C - Codeforces

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#include<queue> 
typedef long long ll;
using namespace std;
int col[200005],row[200009];
int dc[200009],dr[200009];
int n,q;
int lowbit(int x){
    return x&(-x);
}
int query(int x,int k[]){
    int s=0;
    for(;x;x-=lowbit(x)) s+=k[x];
    return s;
}
void modify(int x,int s,int k[]){
    for(;x<=n;x+=lowbit(x)) k[x]+=s;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),std::cout.tie(0);
    cin>>n>>q;
    for(int i=0;i<q;i++){
        int t;cin>>t;
        if(t==1){
            int x,y;cin>>x>>y;
            if(!dc[x])
            modify(x,1,col);
            if(!dr[y])
            modify(y,1,row);
            dc[x]++,dr[y]++;
        }
        else if(t==2){
            int x,y;cin>>x>>y;
            dc[x]--,dr[y]--;
            if(!dc[x])modify(x,-1,col);
            if(!dr[y])modify(y,-1,row);
            
        }
        else{
            int x1,x2,y1,y2;cin>>x1>>y1>>x2>>y2;
            if(x2-x1+1==query(x2,col)-query(x1-1,col)||y2-y1+1==query(y2,row)-query(y1-1,row))
                cout<<"Yes\n";
            else
                cout<<"No\n";
        }
    }
}

 模板2:区间修改,单点查询

利用差分思想完成

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n[1000009],a[1000009];
int t,k;
int lowbit(int m)
{
    return m&(-m);
}
void update(int i,int x) 
{
    while(i<=t)
    {
        n[i]+=x;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    int ans=0;
    while(i>0)
    {
        ans+=n[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    cin>>t>>k;
    for(int i=1;i<=t;i++)
    {
        cin>>a[i];
        update(i,a[i]-a[i-1]);//数组存的是差分数组
    }
    while(k--)
    {
        int ty;cin>>ty;
        if(ty==2){
            int l;cin>>l;cout<<getsum(l)<<"\n";//单点查询某个点数值
        }
        else{
            int l,r,k;
            cin>>l>>r>>k;
            update(r+1,-k);//对差分前缀和操作 
            update(l,k);//
        }
    }
    return 0;
}

 模板3

区间修改区间查询

比模板2多了个数组

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
ll c[1000009],a[1000009],c2[1000009];
ll t,k;
ll lowbit(ll m)
{
    return m&(-m);
}
void update(ll x,ll d) {
    for(ll i=x;i<=t;i+=lowbit(i)){
        c[i]+=d;c2[i]+=x*d;
    }
}
ll getsum(ll x)
{
    ll ans1=0;
    ll ans2=0;
    for(ll i=x;i;i-=lowbit(i)){
        ans1+=(x+1)*c[i];ans2+=c2[i];
    }
    return abs(ans1-ans2);
}
int main()
{
    cin>>t>>k;
    for(ll i=1;i<=t;i++)
    {
        cin>>a[i];
        update(i,a[i]-a[i-1]);//数组存的是差分数组
    }
    while(k--)
    {
        ll ty;cin>>ty;
        if(ty==2){
            ll l,r;cin>>l>>r;cout<<getsum(r)-getsum(l-1)<<"\n";//单点查询某个点数值
        }
        else{
            ll l,r,k;
            cin>>l>>r>>k;
            update(r+1,-k);//对差分前缀和操作 
            update(l,k);//
        }
    }
    return 0;
}

 

模板:二维树状数组单点修改,区间查询

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll tree[4100][4100];
ll n,m,k;
ll lowbit(ll m){
    return m&(-m);
}
void change(ll x,ll y,ll k){
    for(ll i=x;i<=n;i+=lowbit(i)){
        for(ll j=y;j<=m;j+=lowbit(j))
            tree[i][j]+=k;
    }
}
ll qurey(ll x,ll y){
    ll ans=0;
    for(ll i=x;i;i-=lowbit(i)){
        for(ll j=y;j;j-=lowbit(j))
            ans+=tree[i][j];
    } return ans;
}
int main(){
    scanf("%lld%lld",&n,&m);ll mod;
    while(scanf("%lld",&mod)!=EOF){
        if(mod==1){
            ll x,y,k;cin>>x>>y>>k;
            change(x,y,k);
        }
        else{
            ll x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;
            cout<<(qurey(x2,y2)+qurey(x1-1,y1-1)-qurey(x1-1,y2)-qurey(x2,y1-1))<<endl;
        }
    }
    return 0;
}

 

posted on 2022-05-30 20:17  zesure  阅读(19)  评论(0编辑  收藏  举报

导航