线段树和树状数组

· · 个人记录

关于线段树和树状数组的一些理解

对于线段树主要难的是debug,以下是一些思考

线段树真的好简单 (bushi)啊

A-树状数组

前缀和

int add(int x,int k,int n)
{
    while(x<=n)
    {
        tree[x]+=k;
        x+=lowbit(x);
    }
}

树状数组例题

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&-(x))
#define endl '\n'
#define int long long
const int INF=0x3f3f3f3f;
using ll=long long;
using ld=long double;
#define PB push_back
#define MK make_pair
#define EB emplace_back
#define rep(i,n,m) for(int i=n;i<=m;i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
const int N=10000010;
const int M=1010;
int tree[N];
#define lowbit(x) ((x)&(-x))
int sum(int x)
{
    int ans=0;
    while(x!=0)
    {
        ans+=tree[x];
        x-= lowbit(x);
    }
    return ans;
}
int add(int x,int k,int n)
{
    while(x<=n)
    {
        tree[x]+=k;
        x+=lowbit(x);
    }
}
int solve()
{
    int n,m;
    cin>>n>>m;
    //for(int i=1;i<=n;i++)
    rep(i,1,n)
    {
        int a;
        cin>>a;
        add(i,a,n);
    }
    //for(int i=1;i<=m;i++)
    rep(i,1,m)
    {
        int a,b,c;
        cin>>a>>b>>c;
        if(a==1)
        {
            add(b,c,n);
        }
        if(a==2)
        {
            cout<<sum(c)-sum(b-1)<<endl;
        }
    }
}
signed  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    /*int t;
    cin>>t;
    while(t--)
    {
        solve();
    }*/
    solve();

}

区间修改

设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5}

也就是说b[i]=a[i]-a[i-1];(a[0]=0;),那么a[i]=b[1]+....+b[i];(这个很好证的)。

假如区间[2,4]都加上2的话

发现了没有,$b$数组只有$b[2]和b[5]$变了,因为区间$[2,4]$是同时加上2的,所以在区间内$b[i]-b[i-1]$是不变的. 所以对区间$[x,y]$进行修改,只用修改$b[x]$与$b[y+1]$: $b[x]=b[x]+k;b[y+1]=b[y+1]-k$; - [luogu :P3368 【模板】树状数组 2](https://www.luogu.com.cn/problem/P3368) ```cpp #include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&-(x)) #define endl '\n' #define int long long const int INF=0x3f3f3f3f; using ll=long long; using ld=long double; #define PB push_back #define MK make_pair #define EB emplace_back #define rep(i,n,m) for(int i=n;i<=m;i++) #define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--) const int N=10000010; const int M=1010; int tree[N]; int input[N]; #define lowbit(x) ((x)&(-x)) int sum(int x) { int ans=0; while(x>0) { ans+=tree[x]; x-= lowbit(x); } return ans; } void update(int x,int d,int n) { while(x<=n) { tree[x]+=d; x+= lowbit(x); } } int solve() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { cin>>input[i]; } for(int i=1;i<=m;i++) { int a; cin>>a; if(a==1) { int x,y,z; cin>>x>>y>>z; update(x,z,n); update(y+1,-z,n); } if(a==2) { int x; cin>>x; cout<<input[x]+sum(x)<<endl; } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); /*int t; cin>>t; while(t--) { solve(); }*/ solve(); } ```