推荐博客:
博客园:勿忘初心0924 - 树状数组总结
CSDN:bestsort - 树状数组 数据结构详解与模板(可能是最详细的了)
树状数组
一维 单点修改 + 区间查询
POJ 2352 - Stars
题目链接:http://poj.org/problem?id=2352
- 题目描述:
给定n个星星,坐标为(x,y),按Y坐标升序给出,Y相同的按X坐标升序给出
星星的等级为其坐标轴上 左下区域的星星数(不包含该点,包含正下方及正左方)
输出各个等级的星星数目
- 思路:
题目说明 星星按Y坐标给出,因此先给出的星星其等级不会受到影响。后给出的星星j,其等级就是满足 x[i] < x[j] (i < j) 的星星数,因此可以看作是计算X坐标的前缀和
需要注意 x >= 0, 当x=0时 ,lowerbit(0)=0 易导致死循环
- 代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 4e4;
int s[N]={0},num[N]={0};
int lowbit(int x){
return x & -x;
}
void update(int id){
while(id <= N) s[id] += 1, id += lowbit(id);
}
int solve(int id){
int res = 0;
while(id) res += s[id], id -= lowbit(id);
return res;
}
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
int x,y;
scanf("%d%d",&x,&y);
x++;
update(x);
num[solve(x)-1]++;
}
for(int i = 0; i < n; i++) cout<<num[i]<<endl;
return 0;
}
HDU1166-敌兵布阵
模板题:区间查询 + 单点修改
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int s[N];
int lowbit(int x){
return x & (-x);
}
int qy(int id){
int res = 0;
while (id) res += s[id], id -= lowbit(id);
return res;
}
void updata(int id, int x, int n){
while (id <= n) s[id] += x, id += lowbit(id);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t, n, x, y;
cin >> t;
for (int ti = 1; ti <= t; ti++)
{
memset(s, 0, sizeof s);
cin >> n;
for (int i = 1; i <= n; i++) cin >> x, updata(i, x, n);
cout << "Case " << ti << ":" << endl;
while (1)
{
string aa;
cin >> aa;
if (aa == "End") break;
else if (aa[0] == 'Q') {
cin >> x >> y;
cout << qy(y) - qy(x - 1) << endl;
}
else {
cin >> x >> y;
if (aa[0] == 'S') y = -y;
updata(x, y, n);
}
}
}
return 0;
}
一维 区间修改+ 单点查询
Acwing 242 . 一个简单的整数问题
模板题
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[N] = {0}, s[N] = {0};
int n,m;
int lowbits(int x){
return x & -x ;
}
void update(int id, int x){
while(id <= n) s[id] += x, id += lowbits(id);
}
int query(int id){
int res = 0;
while(id) res += s[id] , id -= lowbits(id);
return res;
}
int main(){
int x;
cin>>n>>m;
for(int i = 1; i <= n; i++) cin>>a[i], update(i, a[i]-a[i-1]);
while(m--){
char c;
int id, l, r, d;
cin>>c;
if(c == 'Q') cin>>id, cout<<query(id)<<endl;
else {
cin>>l>>r>>d;
update(l, d), update(r+1, -d);
}
}
return 0;
}
洛谷 P3368 - 树状数组 2
模板题
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
int a[N] = {0}, s[N] = {0};
int n,m;
int lowbits(int x){
return x & -x ;
}
void update(int id, int x){
while(id <= n) s[id] += x, id += lowbits(id);
}
int query(int id){
int res = 0;
while(id) res += s[id] , id -= lowbits(id);
return res;
}
int main(){
int x;
cin>>n>>m;
for(int i = 1; i <= n; i++) cin>>a[i], update(i, a[i]-a[i-1]);
while(m--){
int c,id, l, r, d;
cin>>c;
if(c == 2) cin>>id, cout<<query(id)<<endl;
else {
cin>>l>>r>>d;
update(l, d), update(r+1, -d);
}
}
return 0;
}
一维 区间修改 + 区间查询
洛谷 P3372 - 线段树 1
模板题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll a[N], sum1[N], sum2[N];
ll n, m;
void update(ll id, ll x){
ll i = id;
while(i <= n) sum1[i] += x, sum2[i] += id*x, i += i & -i;
}
ll query(ll id){
ll res = 0, i = id;
while(i) res += (id+1) * sum1[i] - sum2[i], i -= i & -i;
return res;
}
int main(){
cin>>n>>m;
for(ll i = 1; i <= n ;i++) cin>>a[i], update(i, a[i] - a[i-1]);
while(m--){
ll t, l, r, d;
cin>>t;
if(t == 1){
cin>> l >> r >> d;
update(l, d), update(r+1, -d);
}
else {
cin>> l >> r;
cout<<query(r) - query(l-1)<<endl;
}
}
}
二维 区间修改 + 单点查询
poj 2155 Matrix
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3+10;
int a[N][N]={0}, b[N][N]={0}, n, m;
void updata(int x,int y,int d){
while(x <= n){
int yy = y;
while(yy<= n) b[x][yy] += d, yy += yy&-yy;
x += x&-x;
}
}
void range_updata(int x1,int y1,int x2,int y2,int d){
updata(x1,y1,d);
updata(x1,y2+1,-d);
updata(x2+1,y1,-d);
updata(x2+1,y2+1,d);
}
int query(int x,int y){
int res = 0;
while(x){
int yy = y;
while(yy) res += b[x][yy], yy -= yy&-yy;
x -= x & -x;
}
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n; j++) b[i][j] = 0;
while(m--){
char c;
cin>>c;
if(c == 'C'){
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
range_updata(x1,y1,x2,y2,1);
}
else {
int x,y;
cin>>x>>y;
cout<< query(x,y)%2 <<endl;
}
}
if (t) puts("");
}
return 0;
}