模板:

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;
}

示意图:


1.Ultra-QuickSort

大佬代码:

    //树状数组
#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之前比他大的数。


2.Mishka and Interesting sum

大佬代码:

#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数据结构-树状数组的更多相关文章

  1. 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)

    题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...

  2. 数据结构--树状数组&&线段树--基本操作

    随笔目的:方便以后对树状数组(BIT)以及基本线段树的回顾 例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 例题:hdu 1166 敌兵布阵 T ...

  3. 数据结构--树状数组(黑龙江省第八届大学生程序设计竞赛--post office)

    例题来源: 题目: 1468: Post office 题目描述 There are N(N<=1000) villages along a straight road, numbered fr ...

  4. [数据结构] 树状数组 的C程序实现

    ];//树状数组,用于取区间[x,y]的数据的和 /* & 特殊运算,t&(-t)的值(十进制),就是t在2进制下,从右往左数第一个1出现的位置. 结合树状数组的特殊性质,这个值有用 ...

  5. C++-POJ2352-Stars[数据结构][树状数组]

    /* 虽然题目没说,但是读入有以下特点 由于,输入是按照按照y递增,如果y相同则x递增的顺序给出的 所以,可以利用入读的时间进行降为处理 */ 于是我们就得到了一个一维的树状数组解法啦 值得一提:坐标 ...

  6. C++-POJ2155-Matrix[数据结构][树状数组]

    二维树状数组+叉分 区间修改转化为单点修改 单点查询本来就可视为区间查询 于是本题可解 PS:不知道为什么函数传参数,传的是变量就会出现奇奇怪怪的问题? 所以读入单独写了,还有就是循环的初始化硬是多定 ...

  7. C++-HDU1394-Minimum Inversion Number[数据结构][树状数组]

    给出0~n-1的一个排列,可以整体移动,求逆序对最小值 把数字num[i]的加入,等价于树状数组的第n-num[i]位加1 因为num[i]是第 (n-1)-num[i]+1=n-num[i]大的数字 ...

  8. C++-POJ3321-Apple Tree[数据结构][树状数组]

    树上的单点修改+子树查询 用dfn[u]和num[u]可以把任意子树表示成一段连续区间,此时结合树状数组就好了 #include <set> #include <map> #i ...

  9. C++-HDU1166-敌兵布阵[数据结构][树状数组]

    单点修改+区间查询=树状数组 空间复杂度O(n) 时间复杂度O(mlogn) #include <set> #include <map> #include <cmath& ...

随机推荐

  1. Elasticsearch常见用法-分布式集群

    集群内部工作方式 Elasticsearch用于构建高可用和可扩展的系统.扩展的方式可以是购买更好的服务器(纵向扩展(vertical scale or scaling up))或者购买更多的服务器( ...

  2. vs2019 netocore项目本地程序ip地址访问需修改的配置文件

    IISPress启动项目后,打开IISPress托盘可以看到当前项目 根据图中标识出来的applicationhost.config文件路径,一般为你的项目解决方案目录下的.vs\解决方案文件夹\co ...

  3. C#将异常信息添加到日志

    C#将程序抛出的异常信息添加到错误日志 错误日志是软件用来记录运行时出错信息的文本文件.编程人员和维护人员等可以利用错误日志对系统进行调试和维护. 为程序添加错误日志的好处是当程序有运行错误时,根据错 ...

  4. 最强在线文件格式转换(支持200+文件格式如常用的PDF,DOCX,JPG,GIF,MP3,MP4,FLV,MOBI)(通用)

    网站展示:http://www.alltoall.net/ 分类简洁 支持的所有文件格式展示: 单独展示文档转换: 单独展示PDF转换:

  5. 网络编程系统化学习(1.1.)--socket基础

    大纲 学完该阶段内容,你将会很好的完成如下的面试题 socket面试试题相关: 1.写一个简单的socket程序,实现客户端发送数据,服务端收到数据后,将该内容转发给客户端 2.简要概述一下socke ...

  6. RxJS——订阅(Subscription)

    订阅(Subscription) 什么是订阅?订阅是一个对象,它表示一个处理完就释放(disposable)的资源,是 Observable 的一个执行程序.订阅有一个很重要的方法,unsubscri ...

  7. Flink Time深度解析(转)

    Flink 的 API 大体上可以划分为三个层次:处于最底层的 ProcessFunction.中间一层的 DataStream API 和最上层的 SQL/Table API,这三层中的每一层都非常 ...

  8. H3C 什么是漫游

  9. FreeBSD安装过程

    对于现在版本,安装过程中该使用哪些键,现简单总结: Space:选中/取消选中: Tab:切换,主要是分区界面时用它选择输入行: Enter:确定(并进入下一页): 方向键:在一些子组里更换输入项得用 ...

  10. linux设备驱动程序--bus

    linux 中bus驱动解析 总线(bus)是linux发展过程中抽象出来的一种设备模型,为了统一管理所有的设备,内核中每个设备都会被挂载在总线上,这个bus可以是对应硬件的bus(i2c bus.s ...