树状数组模板

1:树状数组求和模板

n个数a1,a2,a3,,an

支持q个操作:

  1. 1 x d,修改ax=d

  2. 2 x,查询xi=1ai

输入格式

第一行两个整数n,q(1n,q2×105)

接下来一行n个整数a1,a2,,an(1ai109)

接下来q行,每行一个形如1 x d或者2 x的操作,保证1xn,1d109

输出格式

对于每个查询,输出一行,表示答案。

样例输入

5 5
1 2 3 4 5
2 4
1 1 5
2 5
1 2 3
2 3

样例输出

10
19
11
点击查看代码
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n,m;

ll a[300000],c[300000];

int lowbit(ll x)
{
    return x&(-x);
}
void updata(int l_,ll r_)
{
    while(l_ <= n)
    {
        c[l_] += r_;
        l_ += lowbit(l_);
    }
}
void query(int l_)
{
    ll ans = 0;
    while(l_ > 0)
    {
        ans += c[l_];
        l_ -= lowbit(l_);
    }
    cout << ans << "
";
}
void solve()
{
    //int n,m;
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
        updata(i,a[i]);
    }
    while(m--)
    {
        int op;
        cin >> op;
        if(op == 1)
        {
            int l;
            ll r;
            cin >> l >> r;
            updata(l,r-a[l]);
            a[l] = r;
        }
        else
        {
            int l;
            cin >> l;
            query(l);
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    t = 1;
    //cin >> t;
    while(t--)
    {
        solve();
    }
}

2:树状数组求逆序对模板

有 n 个数 a1,a2,,an对于其中的两个数字 x,y如果满足 x 出现的位置在 y 出现的位置前面并且 x 比 y 大,则称 (x,y) 为数组 a的一个逆序对。请问数组 a 的逆序对一共有多少个?形式化的说,请求出有多少组 (i,j) 满足 i<j 并且 ai>aj

输入格式

第一行一个整数 n

接下来一行 n 个整数,a1,a2,,an

输出格式

一行一个数,表示答案。

样例输入

4
4 2 3 1

样例输出

5

样例解释

5 个逆序对分别为 (4,2),(4,3),(4,1),(2,1),(3,1)

数据范围

对于 100%100% 的数据,保证 2n100000,1ain 并且每个数字都只会出现一次。

 

点击查看代码
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 3e5;
int n;
ll a[N],d[N];
int lowbit(int x)
{
    return x&(-x);
}
void updata(ll l,int r)
{
    while(l <= n)
    {
        d[l] += r;
        l += lowbit(l);
    }
}
int query(ll l)
{
    ll sum = 0;
    while(l)
    {
        sum += d[l];
        l -= lowbit(l);
    }
    return sum ;
}
void solve()
{
    cin >> n;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
    }
    ll ans = 0;
    for(int i = 1;i <= n;i ++)
    {
        ans += query(n)-query(a[i]);
        updata(a[i],1);
    }
    cout << ans << "
";
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    t = 1;
    while(t--)
    {
        solve();
    }
}

3:树状数组二分模板

n个数a1,a2,a3,,an

支持q个操作:

  1. 1 x d,修改ax=d

  2. 2 s,查询最大的T(0Tn)满足Ti=1ais

输入格式

第一行两个整数n,q(1n,q2×105)

接下来一行n个整数a1,a2,,an(1ai109)

接下来q行,每行一个形如1 x d或者2 s的操作,保证1xn,1d109,1s1014

输出格式

对于每个查询,输出一行,表示答案。

样例输入

5 5
1 2 3 4 5
2 6
2 5
1 1 100
2 10
2 1000

样例输出

3
2
0
5
点击查看代码
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 3e6;
int n,m;
ll a[N],c[N];
ll lowbit(ll x)
{
    return x&(-x);
}
void updata(ll x,ll y)
{
    while(x<=n)
    {
        c[x] += y;
        x += lowbit(x);
    }
}
ll query(ll x)
{
    ll ans = 0;
    for(int j = 18;j >= 0;j--)
    {
        if(ans + (1 << j) <= n && c[ans + (1 << j)] <= x)
        {
            ans += (1<<j);
            x -= c[ans];
        }
    }
    return ans;
}
void solve()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
        updata(i,a[i]);
    }
    
    while(m--)
    {
    	ll op;
    	cin >> op;
    	if(op == 1)
    	{
    		ll x,y;
    		cin >> x >> y;
    		updata(x,y-a[x]);
    		a[x] = y;
    	}
    	else
    	{
    		ll x;
    		cin >> x;
    		ll ans = query(x);
    		cout << ans << "
";
    	}
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    t = 1;
    while(t--)
    {
        solve();
    }
}

4:二维树状数组模板

n×m个数a1,1,a1,2,a1,3,,a1,m,,an,m

支持q个操作:

  1. 1 x y d,修改ax,y=d

  2. 2 x y,查询xi=1yj=1ai,j

输入格式

第一行三个整数n,m,q(1n,m500,q2×105)

接下来n行每行m个整数a1,1,a1,2,,a1,m,,an,m(1ai,j109)

接下来q行,每行一个形如1 x y d或者2 x y的操作,保证1xn,1ym,1d109

输出格式

对于每个查询,输出一行,表示答案。

样例输入

2 3 5
1 1 4
5 1 4
2 2 3
1 1 1 4
2 1 3
1 2 3 10
2 2 3

样例输出

16
9
25
点击查看代码
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e3;
int n,m,q;
ll a[N][N],c[N][N];
ll lowbit(ll x)
{
    return x&(-x);
}
void updata(ll x,ll y,ll z)
{
	ll w = y;
    while(x<=n)
    {
    	y = w;
    	while(y<=m)
    	{
    		c[x][y] += z;
    		y += lowbit(y);
    	}
        x += lowbit(x);
    }
}
ll query(ll x,ll y)
{
    ll ans = 0,w = y;
    while(x)
    {
    	y = w;
    	while(y)
    	ans += c[x][y],y -= lowbit(y);
    	x -= lowbit(x);
    }
    return ans;
}
void solve()
{
    cin >> n >> m >> q;
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 1;j <= m;j ++)
        cin >> a[i][j],updata(i,j,a[i][j]);
    }
    
    while(q--)
    {
    	ll op;
    	cin >> op;
    	if(op == 2)
    	{
    		ll x,y;
    		cin >> x >> y;
    		ll ans = query(x,y);
    		cout << ans << "
";
    	}
    	else
    	{
    		ll x,y,z;
    		cin >> x >> y >> z;
    		updata(x,y,z-a[x][y]);
    		a[x][y] = z;
    	}
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    t = 1;
    while(t--)
    {
        solve();
    }
}

推荐博客
https://www.cnblogs.com/Last--Whisper/p/13823614.html

原文地址:https://www.cnblogs.com/ljm-xiada/p/17441168.html