问题描述:
给定一个整数序列a[1..N],定义sum[i][j]=a[i]+a[i+l]+……+a[j],将所有的sum[i][j]从小到大排序(其中i,j满足1<=i<=j<=N),得到一个长为N*(N+1)/2的序列,求该序列中的第k个元素。
输入格式(ktm.in)
第一行有两个整数N,k,其中0<N<=20000,1<=k<=N*(N+1)/2,数据保证任何一个sum[i][j]的绝对值不超过2^30。
接下来N行每行一个整数。顺序给出序列a的元素。
输出格式(kth.out)
sum序列中的第k个元素
题解:
这道题据说是noip难度的,如果noip真的考这个我就可以直接退役了.
我讲这道题主要是想讲如何用树状数组来代替平衡树的部分功能,从而节省代码量.
算法是很显然的:首先二分答案.假设答案为k,我们求出所有sum中小于k的个数就行了.算法的瓶颈在于什么找到所有sum中有多少小于k.
先讲讲平衡树的做法:预处理一个s数组,s[i]表示sum[0,i].依次加入s[i],统计s1~s[i-1]中大于s[i]-k的个数即可.利用一个平衡树就可以很简单的做到这些操作.
然而,平衡树不仅代码量较大且常数很高,所以我们考虑利用其他数据结构来实现这一功能.
这个数据结构要支持两种操作:加入:加入一个元素;查找:查找所有元素中比k小的元素个数.
这个东西貌似只有平衡树之类的高级数据结构能做,但是,我们可以只用一个