目录

  • 一.模板题
  • 二.树状数组求逆序对
    • 一.离散化
    • 二.逆序对
    • 三.待解决 P1428 小鱼比可爱

算法详解

一.模板题

模板题
题目描述
如题,已知一个数列,你需要进行下面两种操作:
将某一个数加上 x求出某区间每一个数的和
输入格式
第一行包含两个正整数 n,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 m 行每行包含 3 个整数,表示一个操作,具体如下:
1 x k 含义:将第 x 个数加上 k
2 x y 含义:输出区间 [x,y] 内每个数的和
输出格式
输出包含若干行整数,即为所有操作 2 的结果。
输入 #1

5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4

输出 #1

14
16
#include<bits/stdc++.h>
using namespace std;
#define debug cout<<"OK"<<endl
typedef long long ll;
const int maxn=1e7+1;
const int mod=1e9+7;
int n,m,q1,q2,q3,a;
ll tree[maxn];
inline int lowbit(int x){return x&(-x);}
void update(int x,int k)//树的维护
{for(;x<=n;x+=lowbit(x))tree[x]+=k;
}
//此处可以如是想:lowbit取出的是当前x的最低含一位
//权值位,相加后等于向高位进位,并且已有的数位永远为零
//这就可以推出:每当x值+=lowbit(x)时,都会有进位,并且
//进位后的新x值一定包含所有原来的x值,也就是说,这一步
//充分地向上进位,达到区间和更新的目的。
void build()//建树
{for(int i=1;i<=n;i++){cin>>a;update(i,a);}
}
ll query(int x)//查询
{ll ans=0;for(;x;x-=lowbit(x))ans+=tree[x];return ans;
}
inline ll unite(int x,int y)//求和
{return query(x)-query(y-1);
}
int main()
{cin>>n>>m;build();for(int i=1;i<=m;i++){cin>>q1>>q2>>q3;if(q1==1)update(q2,q3);else cout<<unite(q3,q2)<<endl;}return 0;
}

二.树状数组求逆序对

这种题一般数据较大,所以要用离散化优化

一.离散化

数据过大就用离散化处理,这样把数据转化为1-n的数来代表原来的大小顺序

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int n,ans,a[maxn],b[maxn];
bool cmp(int l,int r)
{return a[l]<a[r];
}
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i],b[i]=i;//b数组记录编号stable_sort(b+1,b+1+n,cmp);//这样排序如果遇见数值相同就不会变换顺序for(int i=1;i<=n;i++)a[b[i]]=i;//离散化处理for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;return 0;
}

输入:

5
100000 10000 1000 100 10

输出:

5 4 3 2 1

二.逆序对

首先要知道什么是逆序对:对于一个数组,如果i > j && a[i] < a[j],这两个数就算一对逆序对,简单来说,所有逆序对的个数和就是找每一个数的前面有几个比他的大的数,他们加起来的和就是逆序对的总数。
P1774 最接近神的人
题目描述
破解了符文之语,小FF开启了通往地下的道路。当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案。而石门上方用古代文写着“神的殿堂”。小FF猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的。而最聪明的人往往通过一种仪式选拔出来。仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素。而用最少的交换次数使原序列变成不下降序列的人即是下一任智者。小FF发现门上同样有着n个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小次数。但小FF不会……只好又找到了你,并答应事成之后与你三七分……
输入格式
第一行为一个整数n,表示序列长度
第二行为n个整数,表示序列中每个元素。
输出格式
一个整数ans,即最少操作次数。
输入输出样例
输入 #1

4
2 8 0 3

输出 #1

3

思路:本题要求的是最少需要交换几次,可以用归并排序,亦可用树状数组来做。具体思路链接

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
int n,a[maxn],b[maxn],tree[maxn];
ll ans;
int lowbit(int x){return x&-x;}
bool cmp(int l,int r)//重载运算符用于离散化
{return a[l]<a[r];
}
void update(int x,int k)//维护树状数组
{for(;x<=n;x+=lowbit(x))tree[x]+=k;
}
ll query(int x)//询问
{ll sum=0;for(;x;x-=lowbit(x))sum+=tree[x];return sum;
}
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i],b[i]=i;stable_sort(b+1,b+1+n,cmp);for(int i=1;i<=n;i++)a[b[i]]=i;for(int i=1;i<=n;i++){update(a[i],1);ans+=i-query(a[i]);//用总个数-小于他的数的个数(非逆序对)=逆序对数}cout<<ans<<endl;return 0;
}

三.待解决 P1428 小鱼比可爱

P1428 小鱼比可爱
题目描述
人比人,气死人;鱼比鱼,难死鱼。小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度。参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱程度,很显然整数越大,表示这只鱼越可爱,而且任意两只鱼的可爱程度可能一样。由于所有的鱼头都朝向左边,所以每只鱼只能看见在它左边的鱼的可爱程度,它们心里都在计算,在自己的眼力范围内有多少只鱼不如自己可爱呢。请你帮这些可爱但是鱼脑不够用的小鱼们计算一下。
输入格式
第一行输入一个整数 n,表示鱼的数目。
第二行内输入 n 个整数,用空格间隔,依次表示从左到右每只小鱼的可爱程度。
输出格式
行内输出 n 个整数,用空格间隔,依次表示每只小鱼眼中有多少只鱼不如自己可爱。
输入输出样例
输入 #1

6
4 3 0 5 1 2

输出 #1

0 0 0 3 1 2

用离散化就会WA,待解决

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1000;
int n,tree[maxn],a[maxn],b[maxn];
int lowbit(int x)
{return x&-x;
}
void update(int x)
{for(;x<=100;x+=lowbit(x))tree[x]++;
}
int sum(int x)
{int s=0;for(;x;x-=lowbit(x))s+=tree[x];return s;
}
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++){cout<<sum(a[i])<<" ";update(a[i]+1);}cout<<endl;return 0;
}

思路
注:如果您通过本文,有(qi)用(guai)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧,日更博主每天在线答疑 ! 当然,也非常欢迎您能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答!( •̀ ω •́ )✧

【数据结构】树状数组 例题剖析相关推荐

  1. 数据结构——树状数组

    我们今天来讲一个应用比较广泛的数据结构--树状数组 它可以在O(nlogn)的复杂度下进行单点修改区间查询,下面我会分成三个模块对树状数组进行详细的解说,分别是树状数组基本操作.树状数组区间修改单点查 ...

  2. js 数组 实现 完全树_算法和数据结构 | 树状数组(Binary Indexed Tree)

    本文来源于力扣圈子,作者:胡小旭.点击查看原文 力扣​leetcode-cn.com 树状数组或二叉索引树(英语:Binary Indexed Tree),又以其发明者命名为 Fenwick 树.其初 ...

  3. 数据结构--树状数组

    文章目录 1. 树状数组 2. 单点修改 3. 区间修改 4. 完整代码 5. 参考文献 1. 树状数组 类似数据结构:线段树(Segment Tree) 树状数组 跟 线段树 的区别: 树状数组能做 ...

  4. 数据结构 —— 树状数组

    [概述] 树状数组又称二叉索引树,常用于高效计算数列的前缀和.区间和,其查询.修改的时间复杂度为 log(n),空间复杂度为 O(n) 树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描. 优点 ...

  5. 2017西安交大ACM小学期数据结构 [树状数组 离散化]

    Problem E 发布时间: 2017年6月28日 12:53   最后更新: 2017年6月29日 21:35   时间限制: 1000ms   内存限制: 64M 描述 给定一个长度为n的序列a ...

  6. 2017西安交大ACM小学期数据结构 [树状数组,极大值]

    Problem D 发布时间: 2017年6月28日 10:51   最后更新: 2017年6月28日 16:38   时间限制: 1000ms   内存限制: 32M 描述 给定一个长度为n的序列a ...

  7. 2017西安交大ACM小学期数据结构 [树状数组]

    Problem C 发布时间: 2017年6月28日 11:38   最后更新: 2017年6月28日 16:38   时间限制: 1000ms   内存限制: 32M 描述 给定一个长度为n的序列a ...

  8. Java数据结构-树状数组

    什么是树状数组?[面试5.0] 使用数组表示多叉树的结构,和优先队列有点类似,区别在于优先队列只表示二叉树 主要用来: 更新数组元素的数值并且求数组前K个元素的总和或平均值 时间复杂度为O(logN) ...

  9. “高级”数据结构——树状数组

    数据结构是每一个程序员都必须要学的,非常重要! 大佬的博客写的真好,虽然我看不懂..... 链接http://www.cnblogs.com/RabbitHu/p/BIT.html

最新文章

  1. 第十六届智能车竞赛线上全国总决赛远程组委会监督腾讯会议
  2. 小程序读取富文本mysql存储_微信小程序API 富文本·EditorContext实例
  3. 漫说中介者模式--创业公司成长记
  4. C语言易错题集 第三部
  5. java 如何检测死锁_Java如何查看死锁
  6. 【Python环境搭建】PyCharm鼠标滚轮改变字体大小 等
  7. IOS基本数据类型之枚举
  8. 各种浏览器css不兼容的写法
  9. maven常见问题处理(3-3)Gradle编译时下载依赖失败解决方法
  10. linux系统中存放用户账号信息的文件是,信息安全技术题库:Linux系统中,用户登录密码的hash是存放在()文件中的。...
  11. 修改 jtable 显示格式
  12. inlfuxdb版本_InfluxDB安装及配置
  13. [转]Java总结篇系列:Java泛型
  14. 第一章:开始启程-你的第一行Android代码
  15. 转载]转如何理解 File's Owner 与 First Responder
  16. mysql 数据库备份的多种方式
  17. 使用jTopo给Html5 Canva中绘制的元素添加鼠标事件_html5教程技巧
  18. Bootstrap中tooltip插件使用 | 爱骇客
  19. 荣耀8更改微信提示音
  20. 内存(DDR/DDR2/DDR3/DDR4)的速度等级和时钟频率———个人笔记

热门文章

  1. 机器人4大坐标系讲解,别在搞混了!
  2. 如何识别出轮廓准确的长和宽
  3. ISE 14.7 调试错误笔记
  4. Docker-理解镜像构成
  5. 公路修建问题(二分+最小生成树)
  6. 交换机多生成树协议MSTP
  7. (7)Zabbix分布式监控proxy实现
  8. 建筑物占据的网格数目的确定(三)
  9. Sweeter Than Fiction - Taylor Swift
  10. 【C++基础学习】C++中的引用