題目大意:操作①:往盒子裡放乙個數。操作②:從盒子裡扔掉乙個數。操作③:查詢盒子裡大於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。這個可以直接二...