CWOJ1197 线段树之查询第k大带修改

链接:https://cwoj.tk/problempage.php?problem_id=1197

怎么做呢?

关键在于Query函数

int Query(int id, int l, int r, int k);

这个函数,返回[1, n]区间中第k个数在哪个位置。我们用线段树的方法,划分每个区间,tree[1].sum表示[1, n]区间有多少个人,tree[2].sum表示[1, n/2]区间有多少个人,tree[3].sum表示[n/2 + 1, n]区间有多少个人…

起初,我们查询Query(1, 1, n, k); 接下来,进行如下判断:if (tree[2].sum >= k) Query(1, 1, n / 2, k); else Query(1, n / 2 + 1, n, k - tree[2].sum);

明白了吗?

对于每个区间,只要它有子区间,就这样子判断。即,如果它左孩子区间的sum不小于当前的k,则往左孩子查,否则往右孩子查,但是k要改为k减去左孩子区间的sum…

当查到一个区间没有子区间时,即其 l 等于 r 时,这个 l 就是要查询的答案,就是[1, n]中第k个数的位置。

okay!只要掌握了这个关键部分,其他操作都可以完成了

代码

//to finish

你可能感兴趣的:(CWOJ1197 线段树之查询第k大带修改)