树上带修改K大,太可怕。。写了树链剖分+线段树套平衡树+二分和dfs序+主席树两种,每种都是写+调试花了将近5个小时!!我实在是太弱了。。
1. 树链剖分+线段树套平衡树+二分
最显然的做法了,没啥好多说的,不过写起来真是麻烦(我太弱),
一不小心就会把线段树和平衡树的节点的域弄混,犯了超级多傻逼错误。。写这题的时候还把自己树链剖分的风格改了一下,以前的实在是太麻烦了。。查询的时候二分答案,统计比当前的k大的数有多少个就行了。。
2. dfs序+主席树
考虑不带修改,那么可以对每个节点维护一颗权值线段树记录它到root的数,类型区间K大的,每个点的新树可以由父节点更新log n个节点来得到,所以初始化是O(Nlog N),查询只要把这两个点和lca的权值权值线段树拉出来,二分答案像上面一样搞就行。。如果这两个点是x,y,lca是p,Ui表示i节点的权值线段树,答案就是Ux+Uy-2*Up再加上p的权值。。
再来想带修改,大思路还是要把树转化成线性序列来搞。。那么就想到dfs序,若修改一个节点的权值,只会改变它的子树上的各点的权值线段树,而这些点再dfs序中又对应的是一段区间,那就有办法了。。用树状数组来维护所有的修改,若点i从a被修改为b,L[i]表示i在dfs序中出现的位置,R[i]表示i的子树上的节点在dfs中出现的最后位置,那么先将L[i]-n的