ACM数据结构-树状数组
模板:
int n;
int tree[LEN]; int lowbit(int x){
return x&-x;
} void update(int i,int d){//index,delta
while(i<=n){
tree[i]+=d;
i+=lowbit(i);
}
} int getsum(int i){
int ans=;
while(i>){
ans+=tree[i];
i-=lowbit(i);
}
return ans;
}
示意图:

大佬代码:
//树状数组
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX 500010
int c[MAX];
int aa[MAX];
int n;
typedef struct nano{
int val;
int order;
}node;
node in[MAX];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
while(x<=n){
c[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s=;
while(x>=)
{
s+=c[x];
x-=lowbit(x);
}
return s;//一开始竟然忘记写了这个语句,还以为树状数组写错了呢
}
bool cmp(node a,node b){
return a.val<b.val;
}
int main(int argc, char *argv[])
{
//freopen("2299.in", "r", stdin);
while(scanf("%d",&n)==&&n){
for(int i=;i<=n;++i)
{
scanf("%d",&in[i].val);
in[i].order=i;
}
sort(in+,in+n+,cmp);
for(int i=;i<=n;++i)
aa[in[i].order]=i;//离散化到小范围来
memset(c,,sizeof(c));
long long ans=;
for(int i=;i<=n;++i)
{
update(aa[i], );
ans+=(i-sum(aa[i]));
}
printf("%lld\n",ans);
}
return ;
}
大佬代码理解:

首先用结构体node:{val,order} 来存输入信息,用sort(in+1,in+n+1,cmp); 来根据val值进行排序,通过代码
for(int i=;i<=n;++i)
aa[in[i].order]=i;
构造数组aa,aa表示第i个数排第aa[i]位。(代码理解:i表示原本的索引,in[i].order表示排序后的索引)
逆序数计算:
for(int i=;i<=n;++i)
{
update(aa[i], );
ans+=(i-sum(aa[i]));
}
ans增量: 索引i之前比他大的数。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x7f7f7f7f
#define FOR(i,n) for(int i=1;i<=n;i++)
#define CT continue;
#define PF printf
#define SC scanf
const int mod=;
const int N=1e6+;
int n,m,c[N],pre[N],sum[N],a[N],ans[N]; struct node{
int l,r,pos;
}ne[N]; int lowbit(int i)
{
return i&(-i);
} void add(int p,int u)
{
while(p<=n)
{
c[p]^=u;
p+=lowbit(p);
}
} int query(int u)
{
int res=;
while(u>=)
{
res^=c[u];
u-=lowbit(u);
}
return res;
} bool cmp(node a,node b)
{
return a.r<b.r;
} map<int,int> mp;
int main()
{
while(~scanf("%d",&n))
{
MM(sum,);MM(pre,);MM(c,);
mp.clear();
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-]^a[i];
if(mp[a[i]]) pre[i]=mp[a[i]];
mp[a[i]]=i;
}
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&ne[i].l,&ne[i].r);
ne[i].pos=i;
}
sort(ne+,ne+m+,cmp);
int i=;
for(int k=;k<=m;k++)
{
for(;i<=ne[k].r;i++)
{
if(pre[i]) add(pre[i],a[i]);
add(i,a[i]);
}
ans[ne[k].pos]=(query(ne[k].r)^query(ne[k].l-)^sum[ne[k].r]^sum[ne[k].l-]);
}
for(int i=;i<=m;i++) printf("%d\n",ans[i]);
}
return ;
}
3.模板编写训练1:P3368 【模板】树状数组 1
代码:
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map> #define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 500010
#define MAX 1<<30
#define V vector<int>
#define ll long long using namespace std; inline int read(){
int s=,w=;
char ch=getchar();
while(ch<=''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*w;
} inline ll max(ll a,ll b){
return a>b?a:b;
} ll N;
ll tree[LEN]; int lowbit(int x){
return -x&x;
} ll getsum(int p){
ll sum=;
while(p>){
sum+=tree[p];
p-=lowbit(p);
}
return sum;
} void update(int p,ll v){
while(p<=N){
tree[p]+=v;
p+=lowbit(p);
}
} int main(){
// freopen("D:\\CbWorkspace\\ACM数据结构\\树状数组\\模板1.txt","r",stdin);
int m,i,t,op;
int a,b;
scanf("%d%d",&N,&m);
for(i=;i<=N;i++){
I("%d",&t);
update(i,t);
}
for(i=;i<=m;i++){
I("%d%d%d",&op,&a,&b);
switch(op){
case :
update(a,b);
break;
case :
printf("%lld\n",getsum(b)-getsum(a-));
break;
}
}
return ;
}
4.模板编写训练1:P3368 【模板】树状数组 2
代码:
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map> #define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 500010
#define MAX 1<<30
#define V vector<int>
#define ll long long using namespace std; inline int read(){
int s=,w=;
char ch=getchar();
while(ch<=''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*w;
} inline ll max(ll a,ll b){
return a>b?a:b;
} ll N;
ll tree[LEN]; int lowbit(int x){
return -x&x;
} ll getsum(int p){
ll sum=;
while(p>){
sum+=tree[p];
p-=lowbit(p);
}
return sum;
} void update(int p,ll v){
while(p<=N){
tree[p]+=v;
p+=lowbit(p);
}
} int main(){
// freopen("D:\\CbWorkspace\\ACM数据结构\\树状数组\\模板2.txt","r",stdin);
int m,i,t,op,pre=;
int a,b,c;
scanf("%d%d",&N,&m);
for(i=;i<=N;i++){
I("%d",&t);
update(i,t-pre);
pre=t;
}
for(i=;i<=m;i++){
I("%d",&op);
switch(op){
case :
I("%d%d%d",&a,&b,&c);
update(a,c);
update(b+,-c);
break;
case :
I("%d",&a);
printf("%lld\n",getsum(a));
break;
}
}
return ;
}
注:使用差分数组
ACM数据结构-树状数组的更多相关文章
- 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)
题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...
- 数据结构--树状数组&&线段树--基本操作
随笔目的:方便以后对树状数组(BIT)以及基本线段树的回顾 例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 例题:hdu 1166 敌兵布阵 T ...
- 数据结构--树状数组(黑龙江省第八届大学生程序设计竞赛--post office)
例题来源: 题目: 1468: Post office 题目描述 There are N(N<=1000) villages along a straight road, numbered fr ...
- [数据结构] 树状数组 的C程序实现
];//树状数组,用于取区间[x,y]的数据的和 /* & 特殊运算,t&(-t)的值(十进制),就是t在2进制下,从右往左数第一个1出现的位置. 结合树状数组的特殊性质,这个值有用 ...
- C++-POJ2352-Stars[数据结构][树状数组]
/* 虽然题目没说,但是读入有以下特点 由于,输入是按照按照y递增,如果y相同则x递增的顺序给出的 所以,可以利用入读的时间进行降为处理 */ 于是我们就得到了一个一维的树状数组解法啦 值得一提:坐标 ...
- C++-POJ2155-Matrix[数据结构][树状数组]
二维树状数组+叉分 区间修改转化为单点修改 单点查询本来就可视为区间查询 于是本题可解 PS:不知道为什么函数传参数,传的是变量就会出现奇奇怪怪的问题? 所以读入单独写了,还有就是循环的初始化硬是多定 ...
- C++-HDU1394-Minimum Inversion Number[数据结构][树状数组]
给出0~n-1的一个排列,可以整体移动,求逆序对最小值 把数字num[i]的加入,等价于树状数组的第n-num[i]位加1 因为num[i]是第 (n-1)-num[i]+1=n-num[i]大的数字 ...
- C++-POJ3321-Apple Tree[数据结构][树状数组]
树上的单点修改+子树查询 用dfn[u]和num[u]可以把任意子树表示成一段连续区间,此时结合树状数组就好了 #include <set> #include <map> #i ...
- C++-HDU1166-敌兵布阵[数据结构][树状数组]
单点修改+区间查询=树状数组 空间复杂度O(n) 时间复杂度O(mlogn) #include <set> #include <map> #include <cmath& ...
随机推荐
- C#:Json字符串、JsonArray字符串处理
今天在做Asp网站开发的时候接受到了一种下面这种样子的字符串: "[ { "mid": "123456", "nid": &quo ...
- 阿里云RDS数据库sql server 导入数据并添加作业小结
在阿里云购买ECS服务器和RDS数据库时,要注意网络类型要一致,最好都是VPC,否则ECS不能在内网访问RDS,只能从外网访问:在RDS控制台左侧,数据库安全性的IP白名单中添加ECS外网IP:在数据 ...
- 基于Jquery的下拉列表控件(个人觉得实用)
Selectize.js Selectize 是一个基于 jQuery 的 <select> UI 控件,对于标签选择和下拉列表功能非常有用. Selectize 的目标是通过简单而强大的 ...
- 创建和使用CI / CD管道【译】【原】
在GitLab 8.8中引入. 介绍 管道是持续集成,交付和部署的顶级组件. 管道包括: 定义要运行的作业的作业.例如,代码编译或测试运行. 定义何时以及如何运行的阶段.例如,该测试仅在代码编译后运行 ...
- Git 理解修改
参考链接:https://www.liaoxuefeng.com/wiki/896043488029600/897884457270432 Git之所以比其他版本控制系统设计得优秀,就是因为Git跟踪 ...
- Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合
Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合 一丶FORM的介绍 1.生成页面可用的HTML标签 2.对用户提交的 ...
- Beego学习笔记5:MVC-VC
MVC-VC 1> 新建一个user.go控制器,其代码如下: package controllers import ( "webapp/models" " ...
- 编写可维护的JavaScript-随笔(六)
避免空比较 If(item !== null){ item.sort(); Item.forEach(function(item){ //执行代码 } } } 以上判断中item期待的是数组类型的,但 ...
- Java 之 lambda 表达式
一.函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,就是“拿什么东西做什么事情”.相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语 ...
- springboot设置访问端口和项目路径
找到,application.properties, 添加如下配置即可 server.port=8088server.servlet.context-path=/