树状数组
只学了一维树状数组,这是三个板子。分享一下。
二维还没学,以后再更。
单点修改,区间查询
LibreOJ - 130 - 树状数组 1 :单点修改,区间查询
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
int n, m;
ll tr[N];
int a[N];
int lowbit(int x)
{
return x & -x;
}
void add(int x, int c)
{
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
ll sum(int x)
{
ll res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) add(i, a[i]);
while(m -- )
{
int k1;
cin >> k1;
if(k1 == 1)
{
int loc, c;
cin >> loc >> c;
add(loc, c);
}
else{
int l, r;
cin >> l >> r;
cout << sum(r) - sum(l - 1) << endl;
}
}
}
区间修改,单点查询
LibreOJ - 131-树状数组 2 :区间修改,单点查询
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
int n, q;
ll tr[N];
int a[N];
int lowbit(int x)
{
return x & -x;
}
void add(int x, int c)
{
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
ll sum(int x)
{
ll res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
int main()
{
cin >> n >> q;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++)
{
add(i, a[i] - a[i - 1]);
}
while(q--)
{
int k1, l;
cin >> k1;
if(k1 == 1)
{
int l, r, x;
cin >> l >> r >> x;
add(l, x), add(r + 1, -x);
}
else
{
int x;
cin >> x;
cout << sum(x) << endl;
}
}
}
区间修改,区间查询
LibreOJ - 132-树状数组 3 :区间修改,区间查询
刚开始x没开long long wa在第0个样例,索性都开long long试试,结果就过了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
int n, m; // n是区间长度。m是操作个数
int a[N];
ll tr1[N]; //维护b[i]的前缀和
ll tr2[N]; //维护b[i] * i的前缀和
ll lowbit(ll x) { return x & -x; }
void add(ll tr[], ll x, ll c) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
ll sum(ll tr[], ll x) {
ll res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
ll prefix_sum(ll x) { return sum(tr1, x) * (x + 1) - sum(tr2, x); }
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> 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--) {
int k1;
cin >> k1;
if (k1 == 1) {
ll l, r, x;
cin >> l >> r >> x;
add(tr1, l, x), add(tr2, l, x * l);
add(tr1, r + 1, -x), add(tr2, r + 1, (r + 1) * -x);
} else {
ll l, r;
cin >> l >> r;
cout << prefix_sum(r) - prefix_sum(l - 1) << endl;
}
}
}