树状数组
0.1
目录
基本概念
树状数组的查询和修改的时间复杂度都是log(n)
,空间复杂度则为O(n)
, 通过将线性结构转化成树状结构,从而进行跳跃式扫描。通常使用在高效的计算数列的前缀和,区间和。
代码实现
单点+区间 修改+查询
#include <cstdio>
#include <iostream>
#define L long long
using namespace std;
L c[500001],x,ans;
int n;
L read()
{
L t=0;int f=1;
char t1=getchar();
while(t1<'0'||t1>'9')
{
if(t1=='-') f=-1;
t1=getchar();
}
while(t1>='0'&&t1<='9')
{
t=t*10+t1-'0';
t1=getchar();
}
return t*f;
}
int lowbit(int t)//寻找父节点
{
return t&(-t);
}
void change_point(int root)
{
while(root<=n)
{
c[root]+=x;
root+=lowbit(root);
}
}
void change_interval(int root)
{
while(root>0)
{
c[root]+=x;
root-=lowbit(root);
}
}
L add_interval(int root)
{
L sum=0;
while(root>0)
{
sum+=c[root];
root-=lowbit(root);
}
return sum;
}
L query_interval(int t1,int t2)
{
return add_interval(t2)-add_interval(t1-1);//前缀和思想
}
int main()
{
int m;
n=read();m=read();
for(int i=1;i<=n;i++)
{
x=read();
change_point(i);
}
for(int i=1;i<=m;i++)
{
int co,t;
t=read();co=read();x=read();
if(t-1)
{
ans=query_interval(co,x);
printf("%lld\n",ans);
}
else
change_point(co);
}
return 0;
}
int main()
{
int m;
n=read();m=read();
for(int i=1;i<=n;i++)
{
x=read();
change_interval(i);x*=-1;
change_interval(i-1);
}
while(m--)
{
int t;
t=read();
if(t-1)
{
int co=read();
ans=add_point(co);
cout<<ans<<endl;
}
else
{
int l=read(),r=read();x=read();
change_interval(r);x*=-1;
change_interval(l-1);
}
}
return 0;
}
求逆序对(poj2299)
没有什么好说的,看函数名称都能明白,记得清零.
#include <cstdio>
#include<cstdlib>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int f[500003],t[500003],x=1;
int n;
struct $
{
int s,c;
}a[500003];
bool aa($ x,$ y)
{
return x.c<y.c;
}
int lowbit(int t)
{
return t&(-t);
}
void change_point(int root)
{
while(root<=n)
{
f[root]+=x;
root+=lowbit(root);
}
}
int add_interval(int root)
{
int sum=0;
while(root)
{
sum+=f[root];
root-=lowbit(root);
}
return sum;
}
int main()
{
while(scanf("%d",&n),n)
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].c);
a[i].s=i;
}
sort(a+1,a+1+n,aa);
for(int i=1;i<=n;i++)
t[a[i].s]=i;
long long ans=0;
for(int i=1;i<=n;i++)
{
change_point(t[i]);
ans+=i-add_interval(t[i]);
}
printf("%lld\n", ans);
}
return 0;
}