树状数组应用汇总(全)

最近树状数组学疯了啊,感觉自己之前学了假的树状数组。
才知道树状数组能干的事情这么多。在这里我给大家总结一下,也方便自己复习。
既然是总结知识点,当然我就不会一一解释了,不过这里我给大家一些其他博主的优秀博客及对应知识点题目,我也会在一些难点及细节稍微点一下,以供未学者学习。
我们的梳理顺序从简到难,如果读者觉得一些地方太容易就请跳过看下面内容。


1.树状数组原理,区间查询及单点修改
最基本的树状数组,如果这里都没学的建议你不要往下看了。
给出几篇优秀的博客,需要的自己学习吧。

-推荐博客:
http://blog.csdn.net/int64ago/article/details/7429868
http://www.cnblogs.com/wuwangchuxin0924/p/5921130.html
-题目:
POJ 2352 Stars
链接:http://poj.org/problem?id=2352

值得注意的是,树状数组修改、查询时,建议使用while来实现,不然容易出错。


2.树状数组的区间修改:
比较难理解,需要一定的数学功底(差分思想)。

-推荐博客:
http://blog.csdn.net/fsahfgsadhsakndas/article/details/52650026
http://www.cnblogs.com/wuwangchuxin0924/p/5921130.html
-题目:
洛谷 P3368 树状数组 2
链接:https://www.luogu.org/problem/show?pid=3368

最需要注意的就是差分查找时一定要差分Right+1与Left-1,才能把差分值转移过来!


3.二维树状数组:
最近在POJ上碰到一题,才知道有这个玩意。
思路还是很巧妙地,用到了容斥原理。

-推荐博客:
http://blog.csdn.net/z309241990/article/details/9615259
http://blog.csdn.net/acm_BaiHuzi/article/details/46819049(也是习题的题解)
-题目:
POJ 2155 Matrix
链接:http://poj.org/problem?id=2155

提醒一下,大家都知道如果树状数组下标出现了0这个程序就Game Over了。
0&-0=0,这不就无限循环跑死你。
所以在容斥时,请将扩展的部分放在矩阵的右下角,防止出现0的情况。
提醒:上面的第二篇博客有一个小错误:

void add(int i,int j,int x) {  
    while(i<=n+1) {     //!!!!!应该是n+1不是n!(读者自己想想为什么)  
        int jj=j;  
        while(jj<=n+1) {  //!!!!!同上
            bit[i][jj]+=x;  
            jj+=jj&-jj;  
        }  
        i+=i&-i;  
    }  
}  

好吧我还是说一下为什么吧,由于容斥后出目标部分外其他部分不能变,所以修改时要修改扩展部分(最后1与-1会抵消至没有)。


4.树状数组求逆序对:
一般想到逆序对大家就会想到归并排序,
却不知离散化加树状数组是一个更加快捷的方式。
学一下吧,在考场上压缩运行时间的一大利器!

-推荐博客:
http://blog.csdn.net/acdreamers/article/details/8520096
http://blog.csdn.net/qq_39553725/article/details/76639783
-题目:
POJ 2299 Ultra-QuickSort
链接:http://poj.org/problem?id=2299

这个应用看起来简单,但理解起来是有难度的,编者当初就搜资料,问大佬,看题解弄了好久才彻底搞明白,希望读者们能耐住性子仔细钻研。


5.树形树状数组:
树状数组与树的集合,常见方法为重新编号,并记录新编号节点的管辖区域。
在求解子树权值和的时候还是相当实用的。
但这个应用需要建边,要用到链式前向星,不会的同学先到下面这个博客中学习:
-链式前向星:http://blog.csdn.net/acdreamers/article/details/16902023

-推荐博客:
http://www.cnblogs.com/gj-Acit/p/3236843.html
-题目:
POJ 3321 Apple Tree
链接:http://poj.org/problem?id=3321

由于用到DFS,建边等,还要重新编号,所以元素之间的映射关系会变得比较乱。
读者在自己编程前最好先想清楚变量之间的关系,再动手编程(多打注释!)。
不这么做保准你会后悔的<编到一半自觉删掉重编>!!!!!!!!


6.树状数组求指定长度单调子序列:
这其实就是第4点单调队列求逆序对的升级版。
但由于此时就需要排除两数相等的情况,同时计算多区间符合数量,
就需要用一些特殊技巧了。

-题目:
洛谷 P1637 三元上升子序列
链接:https://www.luogu.org/problem/show?pid=1637
-这一内容的解析请看上题的题解:
https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P1637
http://www.cnblogs.com/zbtrs/p/7078292.html

提醒一下,由于处理了相等数字的情况,线段树的长度有所减少,只有元素个数cnt长度,所以修改、查询时,pos<=cnt而不是pos<=N!


小结:
树状数组的应用肯定还有很多,这里的只不过是冰山一角,其实更多情况下,树状数组要与其他算法合用(如二分答案、前缀和优化之类的)才能发挥出最大的威力,希望上述内容对各位的思维能有所启发,更加深入的内容还望读者自己钻研,毕竟信息学的比赛就是算法设计的比赛,所以,加油吧,各位oier!!!!


虽然我转载了大量别人的博客,但转载这篇我的博客还是要声明出处的哦.(学学我!)

你可能感兴趣的:(树状数组)