如果是初学者建议先看看这篇博客,写的很不错传送门
目录
HDU 1166 敌兵布阵(线段树)
HDU 1698 Just a Hook(线段树)
POJ 3468 A Simple Problem with Integers(线段树区间修改+求和)
HDU 1540 Tunnel Warfare(最长连续区间+单点修改)
洛谷 P3372 【模板】线段树 1
洛谷 P3373 【模板】线段树 2
洛谷 P1198 [JSOI2008]最大数(线段树或RMQ)
洛谷 P1531 I Hate It(线段树或树状数组)
2018年全国多校算法寒假训练营练习比赛(第五场)逆序数(树状数组)
2018年全国多校算法寒假训练营练习比赛(第五场)H Tree Recovery(线段树)
power oj 2821: 小Y学长的GCD难题(线段树区间求最大公因数+区间修改)
区间 (interval)(牛客小白月赛5)(差分)
POJ2299 Ultra-QuickSort(树状数组求逆序数)
HDU4000 Fruit Ninja(树状数组)
POJ2481 Cows(树状数组)
POJ 1990 MooFest(树状数组)
POJ 3264 Balanced Lineup(RMQ)
HDU 1166 敌兵布阵(线段树)
题解:线段树的模板题,但是用树状数组更简单一点,这里前面的这个树状数组的代码,后面的是线段树的代码。
树状数组:
#include
#include
#include
#include
#include
线段树:
#include
#include
#include
#include
#include
HDU 1698 Just a Hook(线段树)
题解:这个题看题就知道是一个很裸线段树的区间修改问题。
#include
#include
#include
#include
#include
POJ 3468 A Simple Problem with Integers(线段树区间修改+求和)
#include
#include
#include
#include
#include
HDU 1540 Tunnel Warfare(最长连续区间+单点修改)
题意:
操作一:某个村庄被毁灭。
操作二:给出一个村庄的坐标,求包含包含这个村庄的的最长未被村庄的长度。
操作三:最后一个被摧毁的村庄被修复。
题解:首先我们可以想到用线段树来维护最长连续区间长度,我们现在可以用1代表改点没有被破坏,用0表示改点被破坏,然后用一个栈或数组来装上次破坏的点。然后就是线段树维护1的最长长度了。
#include
#include
#include
#include
#include
洛谷 P3372 【模板】线段树 1
题解:裸的线段树。
#include
#include
#include
#include
#include
洛谷 P3373 【模板】线段树 2
题解:还是一个线段树的裸题,但是在区间修改的时候,他要乘上一个数,这时候懒标记下放,是要把下面要加的懒标记和要乘的懒标记的都要下放。
#include
#include
#include
#include
#include
洛谷 P1198 [JSOI2008]最大数(线段树或RMQ)
题解:这是一个裸的线段树和RMQ的题,这里把这两种代码都贴出来。
#include
#include
#include
#include
#include
线段树:
#include
#include
#include
#include
#include
洛谷 P1531 I Hate It(线段树或树状数组)
题解:裸的线段树。
线段树:
#include
#include
#include
#include
#include
2018年全国多校算法寒假训练营练习比赛(第五场)逆序数(树状数组)
题解:裸的数组树状数组求逆序数,所以可以声明一个数组,记录比当前位置大的数,因为逆序数,正好是前面出现的比后面大的数,所以只要在前面输入一个数,就把比他小的数的数组加一,最后直接加数组里的数,就是前面比当前输入数大的数的个数。
#include
#include
#include
#include
#include
#include
2018年全国多校算法寒假训练营练习比赛(第五场)H Tree Recovery(线段树)
#include
#include
#include
#include
#include
power oj 2821: 小Y学长的GCD难题(线段树区间求最大公因数+区间修改)
#include
#include
#include
#include
#include
区间 (interval)(牛客小白月赛5)(差分)
题解:可以用线段树做,但是那样有点麻烦,这里可以用差分,这样只用更新,边界节点了。具体思想可以看代码理解。
#include
#include
#include
#include
#include
POJ2299 Ultra-QuickSort(树状数组求逆序数)
题解:前面已经有类似题了,但是没有说清楚,这里说的比较详细点。
这个需要用到离散化,
建立一个结构体包含val和id, val就是输入的数,id表示输入的顺序。然后按照val从小到大排序,如果val相等,那么就按照id排序。如果没有逆序的话,肯定id是跟i(表示拍好后的顺序)一直一样的,如果有逆序数,那么有的i和id是不一样的。所以,利用树状数组的特性,我们可以简单的算出逆序数的个数。
如果还是不明白的话举个例子。(输入4个数)
输入:9 -1 18 5
输出 3.
输入之后对应的结构体就会变成这样
val:9 -1 18 5
id: 1 2 3 4
排好序之后就变成了
val : -1 5 9 18
id: 2 4 1 3
2 4 1 3 的逆序数 也是3
之后再利用树状数组的特性就可以解决问题了;
因为数字可能有重复, 所以添加操作不再单纯的置为1 ,而是 ++;
#include
#include
#include
#include
#include
#include
HDU4000 Fruit Ninja(树状数组)
题意:给出n个数,求所有的i
题解:题目也就是让最后那个数第二大。我们输入第i个数字a,那么我们用的树状数组存的就是sum(a-1),sum(a-1)表示在a这个位置,在前i-1个数中,有sum(a-1)个数比a小,那么我们就可以求出在后面的(i+1,n)的序列中,有R=(n-a)-(i-1-sum(a-1))个数比a要大,(n-a)表示有这么多个数比a大,(i-1-sum(a-1))表示前i-1个数里面有sum(a-1)个数比a大,那么R=(n-a)-(i-1-sum(a-1))就表示后面有多少个数比a要大。然后,我们思考一下,a当作三个数里面的最小值,然后让它们组合,是不是就是有C(R,2)即R*(R-1)/2,因为后面的序列都是固定的,所以并没有排序的概念,也就是说,原本序列1 5 4 ,那么我们没有必要去思考1 4 5的情况,因为它已经固定好了,所以后面的序列选的时候直接从R个选2个就可以了,然后C(R,2)表示所有的a+两个大的(也就是小中大,小大中都包含在里面了),那么我们要求的是小大中,所以对于每一个a来说,我们都需要减去小中大的情况,那么小中大=sum(a-1)*R,所以最后答案就是对于(1,n)所有数,求和SUM(C(R,2)-sum(a-1)*R。
#include
#include
#include
#include
#include
#include
POJ2481 Cows(树状数组)
题意:先说下题意吧,其实就是输入一些线段,问能找到这条线段最多包含几条线段If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。
题解:这样问题就很简单了,我们可以按照后节点从大到小排序,如果后节点相等,前节点从小到大排序。这样排完序后,我们只需要找前面比前节点小的节点的个数就行了。
#include
#include
#include
#include
#include
#include
POJ 1990 MooFest(树状数组)
题意:当两头牛i,j交流的时候,交流的最小声音为max{v[i],v[j]}*他们之间的距离。现在有n头牛,求他们之间两两交流最少要的音量和。
题解:如果用暴力的话肯定会超时的,所以现在可以用树状数组。首先将牛按发出声音的值,按从小到大排序。然后声明两个数组,一个记录当前输入的牛的前面位置比它小的牛的个数,一个记录这些牛的位置和。现在就是怎么求当前牛与其他牛的不同值了。这个分两部分计算,一个是位置比当前牛小的牛和位置比当前牛大的牛。位置小的牛很好计算,就是当前牛的听力值乘以比当前牛位置小的所有牛的位置差。比它大的牛计算有点麻烦。现在用树状数组求出当前输入的所有牛的位置和,减去位置比它小的牛的位置和,位置比它大的牛的位置和。在乘以他的听力值,就是这头牛与其他牛的所有不同值得和,因为按听力排序的,所以当前牛的听力值是最大的,直接乘就行了。
#include
#include
#include
#include
#include
POJ 3264 Balanced Lineup(RMQ)
题解:这个题可以用线段树维护,但是这里用RMQ更方便。
#include
#include
#include
#include
#include