HDU 2852 樹狀陣列 無序第K小

2021-09-08 11:01:05 字數 1405 閱讀 6866

題目大意:操作①:往盒子裡放乙個數。操作②:從盒子裡扔掉乙個數。操作③:查詢盒子裡大於a的第k小數。

解題思路

由於模型是盒子,而不是序列,所以可以用樹狀陣列的順序維護+逆序數思想。

對應的樹狀陣列solution:

$add(val,1)$

類似維護逆序數的方法,對應位置上計數+1。

注意add的while範圍要寫成$while(x如果範圍不是最大,那麼會導致某些sum[x]不會被更新。

判斷:$getsum(val)-getsum(val-1)=0$

可以hash處理,但是沒有必要。如果沒有val這個數,那麼$getsum(val)=getsum(val-1)$是必然的。

刪除:$add(val,-1)$

即加上-1,撤銷之前的操作。

查詢比較麻煩。

首先要判斷$getsum(maxn-1)-getsum(val)>=k$

然後,將查詢大於a的第k小數轉化為大於1的第x+k小數。

其中$x=getsum(val)$。然後,對區間$[1,maxn]$進行二分。

二分處理手段比較特殊,主要是由於有重複的數,所以直接找出$\arg \min \limits_ getsum(mid)=x+k$是不行的。

$getsum(mid)=x+k$有時候並不能二分找到。

解決方法是:

$\left\

r=mid \quad (getsum(mid)<=x+k)\\

\\l=mid \quad (other)

\end\right.$

這樣,如果沒有二分到,會最近的最小r作為結果。

$ans=r$

#include "

cstdio

"#include

"map

"#include

"cstring

"#include

"algorithm

"using

namespace

std;

#define ll long long

#define maxn 100005ll sum[maxn];

intval,n,kth,cmd;

int lowbit(int x)

ll getsum(

intx)

return

ret;

}void update(int x,ints)}

ll query(

int a,int

k)

returnr;}

intmain()

else

if(cmd==1

)

else}}

}}

hdu 2852 樹狀陣列

在基礎上加了二分查詢 include include include using namespace std define m 100005 int n,a m int flage int lowbit int i void update int i,int val int sum int i re...

hdu 2852 樹狀陣列

擦 這題 絕逼 坑人 一波n折。touch me 我一開始 用了最簡單 最sb的 一維hash陣列 來做 我看時間2000ms最大數才10w 還以為能過的 果斷tle了 然後 就覺得應該用更高效的資料結構來做了 我去問下了下porker 他一開始和我提了下 splay 不會啊 然後 說 樹狀陣列 查...

HDU2852 樹狀陣列 二分

思路 樹狀陣列是用來標記的!值 區間點!因為這裡值重複是算的,所有樹狀陣列存的是區間上該位置的個數。0 插入則插入。1 if sum x sum x 1 puts no.2 我們知道a 包括a 之前有多少個數x,求第k大的數,也就是求在樹狀陣列中第x k大的數。sum ans x k。這個可以直接二...