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& ...
随机推荐
- -UI调试工具 SAK 布局 MD
目录 目录 SwissArmyKnife 接入方式 自动初始化版本 支持的功能 可配置项 原理 自定义功能 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndro ...
- c# .netcore oracle连接工具类
1.先右键->添加NeGet包->引入Oracle.ManagedDataAccess.dll 2.将该类加入项目中 工具类: using System; using System.Col ...
- Smack 4.3.4 API
Smack 4.3.4 API 包 包 描述 org.igniterealtime.smack.smackrepl Smack的REPL(读取评估打印循环). org.jivesoftware.s ...
- 多态性 类(class)的四则运算
我们知道c语言中可以整型数据或浮点型等做四则运算,而自己写的类也可做四则运算,是不是感觉奇怪,可以看以下代码是如何完成类之间的四则运算: #include "stdafx.h" ...
- 关于乌班图18.04安装mysql不提示设置密码解决方案
1.下载安装mysql sudo apt-get update sudo apt-get install -y mysql-server mysql-client //下载mysql 运行mysql时 ...
- SQL Server 2017 下载及安装详细教程
SQL Servicer 2017 下载及安装 1)下载安装SQLServer 2)安装SQLServer management Studio. 一. 下载及安装SQLServer 下载链接( ...
- chrome截屏的方法
原文本文链接:https://blog.csdn.net/xiaofengzhiyu/article/details/94652057 Chrome保存整个网页为图片保存为图片右键检查快捷键Ctrl+ ...
- python基础--数据结构之字典
字典 特点:无序,键唯一 目录 1.字典的创建 2. .setdefault 的使用 3. 字典中的查找 4.字典中的改 5. 字典中的删除 6. 打印字典的方法 7. 格式化字符串 8. 合并字符 ...
- JavaScript 数组(一)数组基础
一.数组 1.概述 数组 就是将多个元素按一定顺序排放到一个集合中,那么这个集合称之为数组. 数组 也是一种数据类型,属于复杂数据类型(Object). 2.特点 存放的元素有序的. 可以存放不同的数 ...
- Android中控件AutoCompleteTextView的使用方法和一些属性
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...