详细内容可参考博客:
树状数组
树状数组1
P3374 【模板】树状数组 1
传送门
Code
#include <iostream>
#include <cstdio>
using namespace std;
inline int yread()
{
int x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n,m,c[500050];
inline void add(int x, int val)
{
for (; x <= n; x += x & -x) c[x] += val;
}
inline int yask(int x)
{
int ans = 0;
for (; x; x -= x & -x) ans += c[x];
return ans;
}
int main()
{
n = yread(), m = yread();
for (int i = 1; i <= n; ++i)
{
int x = yread();
add(i, x);
}
for (int i = 1; i <= m; ++i)
{
int opt = yread(), x = yread(), y = yread();
if (opt == 1) add(x, y);
else printf("%d\n",yask(y) - yask(x - 1));
}
return 0;
}
P3368 【模板】树状数组 2 & 242. 一个简单的整数问题
传送门
P3368 【模板】树状数组 2
242. 一个简单的整数问题
算法分析
Code
//P3368 【模板】树状数组 2
#include <iostream>
#include <cstdio>
using namespace std;
inline int yread()
{
int x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 500050;
int n,m,a[maxn],c[maxn];
inline void add(int x, int val)
{
for (; x <= n; x += x & -x) c[x] += val;
}
inline int yask(int x)
{
int ans = 0;
for (; x; x -= x & -x) ans += c[x];
return ans;
}
int main()
{
n = yread(), m = yread();
for (int i = 1; i <= n; ++i)
a[i] = yread();
for (int i = 1; i <= m; ++i)
{
int opt = yread();
if (opt == 1)
{
int x = yread(), y = yread(), k = yread();
add(x, k); add(y + 1, -k);
}
else
{
int x = yread();
printf("%d\n",a[x] + yask(x));
}
}
return 0;
}
//242. 一个简单的整数问题
#include <iostream>
#include <cstdio>
using namespace std;
inline int yread()
{
int x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 100050;
int n,m,a[maxn],c[maxn];
inline void add(int x, int val)
{
for (; x <= n; x += x & -x) c[x] += val;
}
inline int yask(int x)
{
int ans = 0;
for (; x; x -= x & -x) ans += c[x];
return ans;
}
int main()
{
n = yread(), m = yread();
for (int i = 1; i <= n; ++i)
a[i] = yread();
for (int i = 1; i <= m; ++i)
{
char opt; scanf("%c",&opt);
if (opt == 'C')
{
int x = yread(), y = yread(), k = yread();
add(x, k); add(y + 1, -k);
}
else
{
int x = yread();
printf("%d\n",a[x] + yask(x));
}
}
return 0;
}
243. 一个简单的整数问题2
传送门
算法分析
温馨提示:
本题数据有误
有一组数据的指令后面有一个空格,会把scanf和getchar()卡掉
Code
//树状数组
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
inline ll yread()
{
ll x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 100050;
int n,m,a[maxn];
ll c[2][maxn],sum[maxn];
inline void add(int k, int x, int val)
{
for (; x <= n; x += x & -x) c[k][x] += val;
}
inline ll yask(int k, int x)
{
ll ans = 0;
for (; x; x -= x & -x) ans += c[k][x];
return ans;
}
int main()
{
n = yread(), m = yread();
for (int i = 1; i <= n; ++i)
{
a[i] = yread();
sum[i] = sum[i-1] + a[i];
}
for (int i = 1; i <= m; ++i)
{
char opt; cin >> opt;
if (opt == 'C')
{
int l = yread(), r = yread(), d = yread();
add(0, l, d); add(0, r + 1, -d);
add(1, l, d * l); add(1, r + 1, -d * (r + 1));
}
else
{
int l = yread(), r = yread();
ll ans = (sum[r]+(r+1)*yask(0,r)-yask(1,r))-(sum[l-1]+l*yask(0,l-1)-yask(1,l-1));
printf("%lld\n",ans);
}
}
return 0;
}
//这之前用分块写的,可见树状数组的代码量很小
#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
inline ll read()
{
ll x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 100050;
ll n,m,a[maxn],l,r,d,ans;
ll bk,bl[maxn],lazy[maxn],L[maxn],R[maxn],sum[maxn];
inline void add(ll l, ll r, ll d)
{
int p = bl[l], q = bl[r];
if (p == q)
{
for (int i = l; i <= r; i++) a[i] += d;
sum[p] += d * (r - l + 1);
} else
{
for (int i = p + 1; i <= q - 1; i++) lazy[i] += d;
for (int i = l; i <= R[p]; i++) a[i] += d;
sum[p] += (R[p] - l+1) * d;
for (int i = L[q]; i <= r; i++) a[i] += d;
sum[q] += (r - L[q] + 1) * d;
}
}
inline ll ask(ll l, ll r)
{
ll p = bl[l], q = bl[r];
ll ans = 0;
if (p == q)
{
for (int i = l; i <= r; ++i)
ans += a[i];
ans += lazy[p] * (r - l + 1);
}else
{
for (int i = p + 1; i <= q - 1; i++)
ans += sum[i] + lazy[i] * (R[i] - L[i] + 1);
for (int i = l; i <= R[p]; i++) ans += a[i];
ans += (R[p] - l + 1) * lazy[p];
for (int i = L[q]; i <= r; i++) ans += a[i];
ans += (r - L[q] + 1) * lazy[q];
}
return ans;
}
int main()
{
n = read(), m = read();
bk = sqrt(n);
for (int i = 1; i <= n; ++i) a[i] = read();
for (int i = 1; i <= bk; i++)
{
L[i] = (i - 1) * bk + 1;
R[i] = i * bk;
}
if (R[bk] < n) bk++, L[bk] = R[bk - 1] + 1, R[bk] = n;
for (int i = 1; i <= bk; i++)
for (int j = L[i]; j <= R[i]; j++)
bl[j] = i, sum[i] += a[j];
char c;
for (int i = 1; i <= m; ++i)
{
cin >> c;
if (c == 'C')
{
l = read(), r = read(), d = read();
add (l, r, d);
}
else if (c == 'Q')
{
l = read(), r = read();
printf("%lld\n",ask(l, r));
}
}
return 0;
}