树状数组直接搜狗百科就行(不行再去B站)
#include<iostream>
using namespace std;
const int maxn=1e5;
int f[maxn];
int n;
int lowbit(int x){
return x&(-x);
}
void update(int i,int x){//将i位置+x
while(i<=n){
f[i]+=x;
i=i+lowbit(i);
}
}
int query(int n){//求1-n的和
int sum=0;
while(n){
sum+=f[n];
n=n-lowbit(n);
}
return sum;
}
int main(){
cin>>n;
int a;
for(int i=1;i<=n;i++){
cin>>a;
update(i,a);
}
int m;
cin>>m;
for(int i=1;i<=m;i++){
int x,y,p;
cin>>p>>x>>y;
if(p==1)
cout<<query(y)-query(x-1)<<endl;
else
update(x,y);
}
return 0;
}
这道题的思路并不难,但我当时题目的理解有问题
看了题解后发现这道题的坑点有点多
1.坐标可以为0,而树状数组的坐标从1开始,所以需要x++
2.update时的上限不再是n
#include<iostream>
using namespace std;
const int maxn=1e5;
int f[maxn+5];
int sum[maxn+5];
int n;
int lowbit(int x){
return x&(-x);
}
void update(int i,int x){
while(i<=maxn){
f[i]+=x;
i=i+lowbit(i);
}
}
int query(int y){
int sm=0;
while(y){
sm+=f[y];
y=y-lowbit(y);
}
return sm;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
sum[query(x+1)]++;
update(x+1,1);
}
for(int i=0;i<n;i++){
cout<<sum[i]<<endl;
}
return 0;
}
这道题是区间修改+区间查询,上面的巨佬的博客里已经有详细的求法,这里我们用另外一种方法
将区间的左端点和右端点分别用(,)表示,那么任意给出一个区间(a , b),其中贯穿的区间个数为b之前(包含b)左括号的个数-
a之前右括号的个数
#include<iostream>
using namespace std;
const int maxn=5*1e4+4;
int n,m;
int rig[maxn],le[maxn];
int lowbit(int x){
return x&(-x);
}
int query(int y){
int ans=0;
while(y){
ans+=rig[y];
y-=lowbit(y);
}
return ans;
}
void update(int i,int x){
while(i<=n){
rig[i]+=x;
i+=lowbit(i);
}
}
int query2(int y){
int ans=0;
while(y){
ans+=le[y];
y-=lowbit(y);
}
return ans;
}
void update2(int i,int x){
while(i<=n){
le[i]+=x;
i+=lowbit(i);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int k,a,b;
cin>>k>>a>>b;
if(k==1){
update(b,1);
update2(a,1);
}
else{
int ans=query2(b)-query(a-1);
cout<<ans<<endl;
}
}
return 0;
}
首先一个初始为0的点,经过奇数次变换,为1,偶数次变换为0,只需要统计变换次数即可
对于一个区间修改,说明此区间所有值都变换了一次,利用差分d[i]=f[i]-f[i-1],
只需修改 l 和 r+1,最后求某个点时如果query(i)为偶数,则为0,奇数为1
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=5*1e5+5;
int d[maxn];
int n,m;
int lowbit(int x){
return x&(-x);
}
void update(int x,int e){
while(x<=n){
d[x]+=e;
x+=lowbit(x);
}
}
int query(int x){
int ans=0;
while(x){
ans+=d[x];
x-=lowbit(x);
}
return ans;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int t;
cin>>t;
if(t==1){
int l,r;
cin>>l>>r;
update(l,1);
update(r+1,-1);
}
else if(t==2){
int k;
cin>>k;
if(query(k)%2==0)
cout<<0<<endl;
else
cout<<1<<endl;
}
}
return 0;
}