看博客的日常
来源:互联网 发布:各编程语言比较 编辑:程序博客网 时间:2024/05/17 03:41
很久没写了,传一篇看树状数组博客的分析,算是日常,过两天将线段树和树状数组一起总结一下。内容如下
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!树状数组处理数据时,一定要注意边界是否有0,最好每个数据自加一次!!!!!!!!!!!
树状数组总结
1核心代码
更新数组数据
void add(int x,int v){//x!=0
While(x<=max){
a[x]+=v;
x+=lowbit(x);//x+=x&-x;
}
}
求和
int sum(int x){
int ans=0;
While(x>0){
ans+=a[x];
x-=lowbit(x);
}
return ans;
}
基本目的,对于一个数组,可以对各个数组的数据进行更新或者求前i组的和,若仅仅按照题意进行更改的话,时间复杂度将为O(n*m),而如果使用树状数组的话,时间复杂度直接变为O(m*lgn)。
关于为何会减小复杂度,见下博客
传送门:http://blog.csdn.net/int64ago/article/details/7429868
其他的简单变形
单点数据更新,求关于区间的数据
UVA1428 Ping pong(树状数组)
http://blog.csdn.net/u013480600/article/details/20912063
树状数组可用于寻找比a[i]小的数的个数(如此说不算准确,详见题目)
Memset(c,0,sizeof(c));
ans=sum(a[i]);
add(a[i],1);
*tips:数组c[i]树状,既可更新维护单个数据,又可求和
2,求逆序数
a1,a2,a3......................an i=1...........n
逆序数为
ans=0;
for(i=1................n){
ans+=i-sum(a[i]);//sum(a[i])所求的是数列中比a[i]小的数的个数,i-sum(),得到的就是前i
//个数中比a[i]大的,也即逆序数
}
POJ 3378 Crazy Thairs(数据集中+DP+树状数组+高精度)
http://poj.org/problem?id=3378
////二维树状数组初探
Tips:
1,离散化
http://blog.csdn.net/gokou_ruri/article/details/7723378
有些数据本身很大,自身无法作为数组的下标保存对应的属性。
如果这时只是需要这堆数据的相对属性,那么可以对其进行离散化处理!
离散化:当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
Etc://此例子改变了各组数的大小,但关系未变,数目未变;另一种离散化需要删除重复元素
node类中,node.v存数值,node.index记录node数组中的下标,当v中的值极大时,无法存储,但其精确数值与本题无关,我们只需了解数组中不同位置的大小关系,由此,按如下代码进行离散化
1. sort(nodes+1,nodes+n+1);
2. int max_num=0;//表示当前重新映射后的最大值
3. a[nodes[1].index]=++max_num;
4. for(int i=2;i<=n;i++)
5. {
6. if(nodes[i].v==nodes[i-1].v) a[nodes[i].index]=max_num;
7. else a[nodes[i].index]=++max_num;
8. }
2,高精度化
当数据极大,超过long long时,用数组来存储大数据,a[0]存储位数,运算工具,原理不难,详见http://wenku.baidu.com/link?url=F3Jr5ly5vZ7NZhgA-VM9yA6E1EnDtxqc-0YmoHKvI4CmiLhSC4wRVa3iaupDLjKbe3AdvDbboIv79J0CzM53Rnh3AgSFheRCxvOqyy25cbS
PS:有空上网搜搜模板(滑稽)
此题为啥要用高精度?因为极端情况,若有5000个数,每个都不同,则结果有C(5,5000)>2^64>long long
HDU 3450 Counting Sequences(树状数组+DP+离散化)///这题要再看两遍,有玄机
http://acm.hdu.edu.cn/showproblem.php?pid=3450
///二维树状数组再探
注意二分
问题:1为啥一定要对9901取膜?
2,temp=(temp+MOD)%MOD;////why
HDU 3743 Frosh Week(树状数组或归并排序求逆序)
http://acm.hdu.edu.cn/showproblem.php?pid=3743
呃,离散加树状数组,没啥可说的。重点在于逆序数的使用
HDU 2838 Cow Sorting(树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=2838
简单的单点数据更新,一个数组记录逆序数,另一个数组记录cost,
注意结果用long long存
POJ 2182 Lost Cows(树状数组,暴力解法)
http://poj.org/problem?id=2182
这个二分法很强,要揣摩揣摩
POJ 1990 MooFest(树状数组+离线处理)
http://poj.org/problem?id=1990
每个node中,一个存音量,一个存坐标。因为普通做法O(n^2)超时。用树状数组优化,我们先将数组按音量大小排序,这样新数列中,只要管左边的就行。ans+=(坐标比i大的与i的距离+坐标比i小的与i的距离)*v[i]。此时,开两个树状数组,a,b。a存新数列中比i坐标小的个数,b存新数列中比i坐标小的坐标和。这样,小的距离和m=a*x[i]-b;大的距离和n=total(此为新数列中前i个的坐标总值)-b-a*x[i];从而求出结果。
区间数据更新,求关于单点的(更改次数等)
HDU 1556 Color the ball(树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=1556
据说线段树做更简单。学完试试。对a到b间的数据更新,则add(a,1);add(b+1,-1);这样就满足题意。结果用sum(i)输出(傻了傻了,想这题时忘了树状数组性质c[i]存储的是前i组的和)。
add(b+1,-1)使得可以进行单点查询。这篇博客中是向上更新,向下统计。其他的很多都是相反的,不知是否只是便于理解才如此。先看看其他区间更新的
Left,单点更新,删除元素
哈希表的预处理,使得时间复杂度变为O(1),有点像链表,但比链表好查找数据,有空看。。。。
http://blog.csdn.net/u013480600/article/details/21547113
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////饶齐//////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
第二篇博客
http://blog.csdn.net/u012860063/article/details/24810563
关于向上(下)更新,向下(上)统计,先自己理解。这篇不错
///////////////////////////////////////////////////////////
Re:0;
树状数组最基本的用法,单点数据更新,求区域和。此时,(目前为止)全部都是向上更新,向下统计
延伸用途1:
逆序数的应用,对于一列数,计算这个数列中数之间的大小关系(与数据的位置有关)。也算是单点数据更新,因为用树状数组每存(更新)一次数据,计算一次
Etc:
HDU2492 Ping pong 树状数组求逆序数
续逆序数:
poj3067 Japan
先要明白要求的公式(x1-x2)*(y1-y2)<=0,这样,我们就能对数对先按一个数据排序,再求另一组数据的逆序数
逆序数变形
Codeforces Round #261 (Div. 2) D. Pashmak and Parmida's problem
这题是什么鬼。。。。。。。。。。。。。。。。。。。
CSU 1335: 高桥和低桥
区域数据更新,统计单点数据。
为啥要二分?傻了。。。。。。105*105*25必然。。。
的确,向下更新,向上统计好理解,另一种也可以,但难理解
/////////////////////////////////////////////////////////////////////////////////
为啥要对数据离散化
http://blog.csdn.net/u012860063/article/details/45460933
这篇博客讲的很好。对于树状数组,更新数据时,其存储很像位存储,不离散化,浪费空间。同时,由于树状数组的特性,使用时常有大数,所以二分求值也是必要的。
多用long long
HDU 4217 Data Structure?
单点数据更新,自认为这题挺不错,树状数组应用的典型。
模拟的话,时间复杂度为O(n^2),所以要用树状数组优化。这里更新原数组数据有特定条件,因此运用二分。
拓展:如果本题要删除一个无序数组中的第ki个元素,则树状数组在开始读入数据时,要add(i,a[i].v)或add(a[i].index,a[i].v),之后在删除时,进行add(a[i].index,-a[i].v)。定义index存储原本位置,之后找第ki个元素时排序。要访问第index个元素,使用sum(a[i].index)-sum(a[i].index-1)。PS:又想了想,要定义二维树状数组,c[1][]处理按大小排列后的数组的下标。要删除原数列元素,就要按上面说的,用第二维操作。
//////////////////////////////////////////////////////////////////////////////////////////////////////tianyiming////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
第三篇博客。。。。
http://blog.csdn.net/wmn_wmn/article/category/896475/1
hdu2642 Stars
另一种二维树状数组。。。。。基本的,据说算裸二维。。。。不难,简单的单点更新,区间查询。新技能get,对面上的点的做法。。
NYOJ 522 裸的树状数组
不想翻译。。。。。。。博主说是水题,那就(滑稽)。。
Enemy is weak 树状数组
求逆序数加离散化。。。。。其实就是pingpang那个题的变形,不对,一样,就是题干换了,但注意要对数据离散化,以及边界不为0。
POJ 3321 Apple Tree
http://poj.org/problem?id=3321
Dfs+树状数组。好题!!用链表存储树上的数据。单点更新,区间查询。难点是将如何将各个子树上的数值统计。可以用dfs遍历,还有,要用一个数组记录节点的状态
1. void dfs(int x){
2. down[x] = order;//down[]记录靠近根节点的数值
3. for(int i = head[x]; i != -1; i = ee[i].next){
4. int y = ee[i].rp;
5. dfs(y);
6. }
7. up[x] = order++; //每遍历一层加一
8. }
上面算是预处理。之后就是套路,将数值存到树状数组中就好,更新时,add(up[i],1);或add(up[i],-1);对节点值取反。
求和sum(up[i])-sum(down[i]-1)
POJ 1195 Mobile phones
裸的二维数组
和star那道题一样,二维数组模板
1. void update(int x,int y,int add){
2. int t = y;
3. while(x < N){
4. y = t;
5. while(y < N){
6. num[x][y] += add;
7. if(num[x][y] < 0)
8. num[x][y] = 0;
9. y += lowbit(y);
10. }
11. x += lowbit(x);
12. }
13. }
14. LL sum(int x,int y){
15. int t = y;
16. LL s = 0;
17. while(x > 0){
18. y = t;
19. while(y > 0){
20. s += num[x][y];
21. y -= lowbit(y);
22. }
23. x -= lowbit(x);
24. }
25. return s;
26. }
在图像中逐行更新
HDU 3584 Cube
裸的三维树状数组
1. update(x2,y2,z2,1);
2. update(x1-1,y2,z2,-1);
3. update(x2,y1-1,z2,-1);
4. update(x2,y2,z1-1,-1);
5. update(x1-1,y1-1,z2,1);
6. update(x1-1,y2,z1-1,1);
7. update(x2,y1-1,z1-1,1);
8. update(x1-1,y1-1,z1-1,-1);
这个更新。。。。。不明白
明天看题意,应该不难。。。。
区间更新,单点查询。向下更新,向上查询
POJ 2029 Get Many Persimmon Trees
同样没找到题意。。。。。。
裸的二维树状数组。。。单点更新,区间查询
HDU 3015 Disharmony Trees
和1990那道题一样,挺有意思的,将最大值改为最小值,更改排序顺序即可,刚看完就有点忘。。。。。
单点更新,区间查询。开俩数组,一个记录原数组下标,一个记录原数组数值。(看完资料写一遍!)PS:博主对原数组排了两边序。。。自己写时看看,感觉一个就可以
- 看博客的日常
- 日常博客
- 看了**的博客
- [02-04]日常好的博客总结
- 常去看的几个博客
- 第一次看老弟的博客
- 我喜欢看的博客
- 必看的VBA博客
- 一些经常看的博客
- ACMer值得看的博客
- 看博客后的反思
- 推荐看的一些博客
- 【Android】日常开发中常见的坑,新手必看
- 日常博客系列规划
- vector的日常笔记 酒馆浪人的博客
- 日常常用的SQL语言 - XueJiang''s Blog - CSDN博客
- 【日常吐槽 · 第七期】进击的博客
- 看博客
- 插入排序/选择排序/交换排序/归并排序/基数排序
- Java的作业
- SortedSet接口与TreeSet实现类(二)
- 第一天
- Map集合常用方法
- 看博客的日常
- C++ 链表实现
- Spring定时任务的简单例子(转载)
- Java-面向对象(高级篇)--接口的基本概念
- C++ primer | 第八章 IO 库
- JSON详解
- GRASS GIS学习一
- iframe页面跳转
- package com.example.eTextView省略和Ellipsize回调监听;