[蓝桥杯学习] 树状数组的二分

[蓝桥杯学习] 树状数组的二分_第1张图片

要解决这个问题,插入和删除可以用STL实现,2操作如果用树状数组实现的话,将数的值作为树状数组的下标,即值域。

树状数组有两种操作,一个是更新某点的值,另一个是求区间和。

[蓝桥杯学习] 树状数组的二分_第2张图片

mid = (l+r)/2 ,求和 t[a+1] 到 t[mid] ,设为x,如果x小于k,就mid右移,如果x大于k,就mid左移

[蓝桥杯学习] 树状数组的二分_第3张图片

二分查找的代码

注意:不同点是,可能第k大的数 c 到第 k+1 大的数 b之间都是到a求和有k个值,所以我们要找左边界,不断更新ans,遇到相等的,先记录下来,然后把mid左移。

int find(int a,int k)
{
  int l = a+1; 
  int r = maxn;
  int mid;
  int ans=-1;
  while(l <= r)
  {
    mid = (l+r) >> 1;
    if(query(mid) - query(a) = k) ans = mid;
    if(query(mid) - query(a) >= k) r = mid-1;
    else l = mid+1; 
  }
  return ans;
}

[蓝桥杯学习] 树状数组的二分_第4张图片

例题

[蓝桥杯学习] 树状数组的二分_第5张图片

第i个小朋友前面有ai个小朋友,如果后面没有比他低的,那么他的身高是 ai+1

如果我们从前往后遍历数组a[i] ,我们是无法知道后面小朋友的身高,所以要从后往前遍历,但是,计算中间小朋友的身高时,还是得知道后面有多少人比他低。

使用树状数组时,从后往前遍历时,每确定一个身高,就把该下标从1变为0,这样,往前计算小朋友身高时,通过求和,就能得到这个小朋友的身高,例:原本是111111,两次删除之后是100111,ai=3的小朋友,ai+1=4,但是很明显,确定身高的小朋友都比他低,所以要后移两位(通过0的存在实现了),移到了6

你可能感兴趣的:(蓝桥杯,学习)