题目连接 New Year Domino
这个题用线段树来离线处理询问(结合代码来看,我觉得看代码还好懂一些);
先设置一个数组,cur[],初始值设置为空,用线段树来维护它.
这个数组的具体含义往后看.
然后从左到右去扫描每个多米诺,比如说现在扫描到第k个了,
那么cur[i](0
这样对于每个询问 (l, r), 当我们扫描到r时,也就是k == r时, cur[l]里面的值就是答案.
那么怎么去更新这个cur[]呢?
假设我们现在扫描到了k, 并且设x[k]和y[k]分别表示k的x坐标和高度
我们考虑第k-1个骨牌, 假设 x[k-1]+y[k-1] < x[k], 那么就肯定需要把它的高度增加 x[k] - x[k-1] - y[k-1]; 如果 x[k-1]+y[k-1] >= x[k] 就不用管.
接着我们考虑第k-2个个骨牌, 因为我们之前扫描过k-1了,所以现在k-2骨牌倒下后肯定能够碰到第k-1个骨牌,
然后现在有两种方法让k-2碰倒第k个,
一:k-2倒下后直接喷到k, 需要增加的长度是 tmp1 = x[k] - x[k-2] - y[k-2]
二:k-2倒下后碰到k-1,k-1再倒下碰到k, 需要增加的长度是 tmp2 = x[k] - x[k-1] - y[k-1](因为k-2倒下后肯定能碰到k-1)
于是我们就比较tmp1和tmp2,选择优的那一个(也就是增加长度少的)
...
下面我们更加整体的来考虑整个模型,可以发现这么一个规律
假设现在我们扫描到了第k个骨牌,它前面肯定存在一个区间 (a1, k-1], 这个区间内的每个多米诺的最优情况都是不直接碰到k,而是先碰倒k-1,然后让k-1碰到k;
然后在(a1, k-1]这个区间前面,肯定还有一个区间(a2, a1], 这个区间每个多米诺的最优情况都是不直接碰到k,而是先碰倒a1, 然后a1碰到k;
接下来就会有(a3, a2] .... [1, ak]
对于(a1, k-1]这个区间内的cur[], 都需要增加 max(x[k] - x[k-1] - y[k-1], 0);
对于(a2, a1]这个区间内的cur[], 都需要增加 max(x[k] - x[a1] - y[a1], 0);
...
于是可以用线段树来维护cur[](区间更新嘛)
现在的问题就变成了怎么去找 a0(我们令a0 = k-1), a1, a2, a3 ... ak;
其实可以发现 x[ai] + y[ai] < x[a(i+1)] + y[a(i+1)] 并且 x[ai] + y[ai] >= x[j] + y[j] ( a(i+1)
然后就可以用一个单调队列来维护ai
更具体的看下面代码(我觉得看代码还更好理解)
#include
#include
#include
#include
#include
#include
#include