Link
Solution
可以看出,一个点对于它左边的区间的答案是不会产生影响的,而对右边的区间的影响是遮住了所有与原点连线的斜率比它小的。 于是脑中模模糊糊地浮现出一棵线段树,那棵树上的每个节点长着一棵Treap。 插入一个新节点,把它右边的区间中比它左边区间中斜率最大值大,而又比新插入的点斜率值小的点从右区间的答案中删去。 删除一个节点,把它右边区间中比它的斜率小但比它左边区间中最大值大的点加入答案。 口胡做法不一定对
最后发现,正解的做法非常巧妙。
大致思路差不多,但在更新答案的时候只需要在线段树上走即可。
首先,把新值赋到线段树的对应节点上。回溯的时候考虑已经知道了左半区间和右半区间的答案,如何得到整个区间的答案。思路就是,左半区间的答案不会改变,可以直接累加,而右半区间需要把比左半区间最大值小的点删掉。
对于右半区间递归处理,设左半区间的最大值为。
假如左半区间的最大值
,那左半区间就别想了,只需要统计右半区间有多少的点。
,那左半区间就别想了,直接返回右半区间的答案对答案的贡献,即pos->cnt-pos->son[0]->cnt
,那就不会影响右半区间的答案,只需要统计左半区间有多少的点,加上右半区间的答案即可。
很神奇的思路。每次操作只会走一条到叶节点的路径。单点的修改,把所有的路径长度累加,是,也就是,即总
再加上线段树本来的复杂度,总,常数很小,跑得很快。
Tips
依旧是分析问题性质是最重要的,通过左右区间的影响关系的彻底分析,才得出这种很好写跑得快的方法。
Code
1 | //Code by Lucida |