学习博客:树状数组详解
这里说的树状数组的操作包括:
- 单点修改,区间查询
- 区间修改,单点查询
- 区间修改,区间查询
其中区间的信息为区间和
推导过程以及原理在上面那篇博客中有很详细的介绍,在这里只对一些题目给出模板
- 单点修改,区间查询
题目链接:敌兵布阵
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define lowbit(x) x&(-x)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 5e4+10;
int n;
int a[N];
void update(int i, int key)
{
while(i <= n)
{
a[i] += key;
i += lowbit(i);
}
}
int query(int i)
{
int ret = 0;
while(i > 0)
{
ret += a[i];
i -= lowbit(i);
}
return ret;
}
int main()
{
int t, x, y;
char s[10];
scanf("%d", &t);
for(int ca = 1; ca <= t; ca++)
{
memset(a, 0, sizeof(a));
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
update(i, x);
}
printf("Case %d:\n", ca);
while(scanf("%s", s) && strcmp(s, "End") != 0)
{
scanf("%d %d", &x, &y);
if(strcmp(s, "Query") == 0)
{
printf("%d\n", query(y) - query(x-1));
}
else
{
if(s[0] == 'A') update(x, y);
else update(x, -y);
}
}
}
return 0;
}
- 区间修改,单点查询
题目链接:【模板】树状数组 2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define lowbit(x) x&(-x)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 5e5+10;
int n;
ll a[N];
void update(int i, ll key)
{
while(i <= n)
{
a[i] += key;
i += lowbit(i);
}
}
ll query(int i)
{
ll ret = 0;
while(i > 0)
{
ret += a[i];
i -= lowbit(i);
}
return ret;
}
int main()
{
int m, x, y, op;
ll k;
ll pre = 0;
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%lld", &k);
update(i, k - pre);
pre = k;
}
for(int i = 1; i <= m; i++)
{
scanf("%d", &op);
if(op == 1)
{
scanf("%d %d %lld", &x, &y, &k);
update(x, k);
update(y+1, -k);
}
else
{
scanf("%d", &x);
printf("%lld\n", query(x));
}
}
return 0;
}
- 区间修改,区间查询
题目链接:A Simple Problem with Integers
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define lowbit(x) x&(-x)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int n;
ll a[N];
ll sum1[N], sum2[N];
void update(int i, ll key)
{
int x = i;
while(i <= n)
{
sum1[i] += key;
sum2[i] += key*(x-1);
i += lowbit(i);
}
}
ll query(int i)
{
ll ret = 0;
int x = i;
while(i > 0)
{
ret += x*sum1[i]-sum2[i];
i -= lowbit(i);
}
return ret;
}
int main()
{
int m, x, y;
ll k;
ll pre = 0;
char op;
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%lld", &k);
update(i, k - pre);
pre = k;
}
for(int i = 1; i <= m; i++)
{
getchar();
scanf("%c", &op);
if(op == 'Q')
{
scanf("%d %d", &x, &y);
printf("%lld\n", query(y) - query(x-1));
}
else
{
scanf("%d %d %lld", &x, &y, &k);
update(x, k);
update(y+1, -k);
}
}
return 0;
}