目录
130. 树状数组 1 :单点修改,区间查询
https://loj.ac/p/130
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long int LL;
LL tr[N],n;
int lowbit(int x){
return x&(-x);}
void add(int u,int x)//u位置加x
{
for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x;
}
LL query(int u)//求[1,u]的和
{
LL sum=0;
for(int i=u;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x; cin>>x;
add(i,x);
}
for(int i=0;i<m;i++)
{
int op,a,b; cin>>op>>a>>b;
if(op==1) add(a,b);
else cout<<query(b)-query(a-1)<<endl;
}
return 0;
}
131. 树状数组 2 :区间修改,单点查询
https://loj.ac/p/131
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long int LL;
LL tr[N],a[N],n,m;
int lowbit(int x){
return x&(-x);}
void add(int u,int x)//u位置加x
{
for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x;
}
LL query(int u)//求点u的值
{
LL sum=0;
for(int i=u;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
void init()//初始化差分数列
{
for(int i=1;i<=n;i++) add(i,a[i]-a[i-1]);
}
void solve(int l,int r,int x)//[l,r]加x
{
add(l,x),add(r+1,-x);
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
init();
for(int i=0;i<m;i++)
{
int op; cin>>op;
if(op==1)
{
int l,r,x; cin>>l>>r>>x;
solve(l,r,x);
}
else
{
int x; cin>>x;
cout<<query(x)<<endl;
}
}
return 0;
}
132. 树状数组 3 :区间修改,区间查询
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long int LL;
LL tr1[N],tr2[N],a[N],n,m;
LL lowbit(LL x){
return x&(-x);}
void add(LL tr[],LL u,LL c)
{
for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=c;
}
LL query(LL tr[],LL u)
{
LL sum=0;
for(int i=u;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
LL sum(LL u)
{
return 1ll*(u+1)*query(tr1,u)-query(tr2,u);
}
void init()//初始化
{
for(int i=1;i<=n;i++)
{
add(tr1,i,a[i]-a[i-1]);
add(tr2,i,i*(a[i]-a[i-1]));
}
}
void add_lr(LL l,LL r,LL c)//[l,r]区间内加c
{
add(tr1,l,c),add(tr1,r+1,-c);
add(tr2,l,l*c),add(tr2,r+1,-(r+1)*c);
}
LL query_lr(LL l,LL r)//查询区间[l,r]
{
return sum(r)-sum(l-1);
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
init();
for(int i=0;i<m;i++)
{
int op; cin>>op;
if(op==1)
{
LL l,r,c; cin>>l>>r>>c;
add_lr(l,r,c);
}else
{
LL l,r; cin>>l>>r;
cout<<query_lr(l,r)<<endl;
}
}
return 0;
}
133. 二维树状数组 1:单点修改,区间查询
#include<bits/stdc++.h>
using namespace std;
const int N=5050;
typedef long long int LL;
LL tr[N][N],n,m;
int lowbit(int x){
return x&(-x);}
void add(int x,int y,int v)//[x,y]加v
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j))
tr[i][j]+=v;
}
LL query(int x,int y)
{
LL sum=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j)) sum+=tr[i][j];
return sum;
}
LL query_ans(int x,int y,int xx,int yy)
//找[x,y][xx,yy]为左上角和右下角的矩阵的和
{
return query(xx,yy)-query(xx,y-1)-query(x-1,yy)+query(x-1,y-1);
}
int main(void)
{
cin>>n>>m;
int op;
while(cin>>op)
{
if(op==1)
{
int x,y,k; cin>>x>>y>>k;
add(x,y,k);
}else
{
int x,y,xx,yy; cin>>x>>y>>xx>>yy;
cout<<query_ans(x,y,xx,yy)<<endl;
}
}
return 0;
}
134. 二维树状数组 2:区间修改,单点查询
#include<bits/stdc++.h>
using namespace std;
const int N=5050;
typedef long long int LL;
LL tr[N][N],n,m;
int lowbit(int x){
return x&(-x);}
void add(int x,int y,int v)//[x,y]加v
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j))
tr[i][j]+=v;
}
LL query(int x,int y)//单点查询
{
LL sum=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j)) sum+=tr[i][j];
return sum;
}
void add1(int x,int y,int xx,int yy,int k)//区间加
{
add(x,y,k),add(xx+1,y,-k);
add(x,yy+1,-k),add(xx+1,yy+1,k);
}
int main(void)
{
cin>>n>>m;
int op;
while(cin>>op)
{
if(op==1)
{
int x,y,xx,yy,c; cin>>x>>y>>xx>>yy>>c;
add1(x,y,xx,yy,c);
}else
{
int x,y; cin>>x>>y;
cout<<query(x,y)<<endl;
}
}
return 0;
}
135. 二维树状数组 3:区间修改,区间查询
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5000 + 10;
LL t1[N][N],t2[N][N],t3[N][N],t4[N][N];
int n,m;
int lowbit(int x) {
return x & - x;}
void add(int a, int b, int k)
{
for (int i = a; i <= n; i += lowbit(i))
{
for (int j = b; j <= m; j += lowbit(j))
{
t1[i][j] += k;
t2[i][j] += k * a;
t3[i][j] += k * b;
t4[i][j] += k * a * b;
}
}
}
LL sum(int a, int b)
{
LL ans=0;
for (int i=a;i;i-=lowbit(i))
for (int j=b;j;j-=lowbit(j))
ans+=t1[i][j]*((a+1)*(b+1))-t2[i][j]*(b+1)-t3[i][j]*(a+1)+t4[i][j];
return ans;
}
void add1(int a,int b,int c,int d,int k)
//[a,b][c,d]为左上角和右下角的矩阵所有值加k
{
add(a, b, k);
add(c + 1, d + 1, k);
add(a, d + 1, -k);
add(c + 1, b, -k);
}
LL query_ans(int a,int b,int c,int d)
//求区间[a,b],[c,d]为左上角和右下角的和
{
return sum(a-1,b-1)+sum(c,d)-sum(a-1,d)-sum(c,b-1);
}
int main() {
scanf("%d%d",&n,&m);
int op,a,b,c,d,k;
while(~scanf("%d", &op))
{
if(op==1)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
add1(a,b,c,d,k);
} else
{
scanf("%d%d%d%d",&a,&b,&c,&d);
printf("%lld\n",query_ans(a,b,c,d));
}
}
return 0;
}
P1908 逆序对
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long int LL;
int a[N],tr[N],n;
vector<int>ve;
int lowbit(int x){
return x&(-x);}
void add(int u,int v)
{
for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=v;
}
LL query(int u)
{
LL sum=0;
for(int i=u;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) ve.push_back(a[i]);
sort(ve.begin(),ve.end());
ve.erase(unique(ve.begin(),ve.end()),ve.end());
LL ans=0;
for(int i=1;i<=n;i++)
{
int l=upper_bound(ve.begin(),ve.end(),a[i])-ve.begin();
//找到第一个大于a[i]的下标,从0开始
ans+=query(n)-query(l);
add(l,1);
}
cout<<ans;
return 0;
}