前言
最近在复习算法的时候,刷到了一些针对于区间问题,所以在此记录。
注:此文章默认会使用树状数组,不会的可以参考这一篇文章:树状数组详解
一. 单点修改,单点查询
这个很简单,我们直接使用单纯的数组就可以了。
二. 单点修改,区间查询
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int tree[N], a[N];
int n, m;
int lowbit(int i){
return i & (-i);
}
void modify(int i, int k){
int x = i;
while(i <= n){
tree[i] += k;
i += lowbit(i);
}
}
int query(int i){
int x = i, res = 0;
while(i){
res += tree[i];
i -= lowbit(i);
}
return res;
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
modify(i, a[i]);
}
while(m--){
char op;
cin >> op;
if(op == 'Q'){
int l, r;
cin >> l >> r;
cout << query(r) - query(l - 1) << '\n';
}else{
int i, k;
cin >> i >> k;
modify(i, k);
}
}
return 0;
}
三. 区间修改,单点查询
我们这里考虑用树状数组+差分。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int tree[N], a[N];
int n, m;
int lowbit(int i){
return i & (-i);
}
void modify(int i, int k){
int x = i;
while(i <= n){
tree[i] += k;
i += lowbit(i);
}
}
int query(int i){
int x = i, res = 0;
while(i){
res += tree[i];
i -= lowbit(i);
}
return res;
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
modify(i, a[i] - a[i - 1]);
}
while(m--){
char op;
cin >> op;
if(op == 'Q'){
int i;
cin >> i;
cout << query(i) << '\n';
}else{
int l, r, k;
cin >> l >> r >> k;
modify(l, k);
modify(r + 1, -k);
}
}
return 0;
}
四. 区间修改,区间查询
这个稍微难点,详解可以看我在前言发的那篇文章。
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
ll tree1[N], tree2[N], a[N];
ll n, m;
ll lowbit(ll i){
return i & (-i);
}
void modify(ll i, ll k){
ll x = i;
while(i <= n){
tree1[i] += k;
tree2[i] += (x - 1) * k;
i += lowbit(i);
}
}
ll query(ll i){
ll x = i, res = 0;
while(i){
res += x * tree1[i] - tree2[i];
i -= lowbit(i);
}
return res;
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
modify(i, a[i] - a[i - 1]);
}
while(m--){
char op;
cin >> op;
if(op == 'Q'){
int l, r;
cin >> l >> r;
cout << query(r) - query(l - 1) << '\n';
}else{
int l, r, k;
cin >> l >> r >> k;
modify(l, k);
modify(r + 1, -k);
}
}
return 0;
}