因為需要支援插入,所以外層需要乙個平衡樹,替罪羊樹比較好寫
內層需要帶修改,求k小值,可以使用權值線段樹維護平衡樹每個節點子樹內的所有權值,求k小值時二分查詢
所以是平衡樹套權值線段樹
#include#include帶插入區間k小值#include
#include
#include
using
namespace
std;
int n,val[70005],dfn[70005],root,rt[70005
],m,las;
const
float alpha=0.75
;char opt[70005
];inline
intread()
while(ch>='
0'&&ch<='
9')w=(w<<1)+(w<<3)+ch-'
0',ch=getchar();
return f*w;
}namespace
sgt
return ++cnt;
}inline
void pushup(int i)
void recyc(int &i)
void update(int &i,int l,int r,int p,int
v)
int mid=l+r>>1
;
if(p<=mid)update(lc[i],l,mid,p,v);
else update(rc[i],mid+1
,r,p,v);
pushup(i);
if(!sum[i])recyc(i);
}}namespace
bst
int mid=l+r>>1
; i=dfn[mid];
build(lc[i],l,mid-1),build(rc[i],mid+1
,r);
for(int j=l;j<=r;j++)sgt::update(rt[i],0,70000,val[dfn[j]],1
); }
void del(int &k)
void rebuild(int &k)
int dfs(int k,int x,int
v)
void insert(int &k,int x,int
v) sgt::update(rt[k],
0,70000,v,1
);
int temp=sgt::sum[rt[lc[k]]];
if(temp>=x)insert(lc[k],x,v);
else insert(rc[k],x-temp-1
,v);
if((double)sgt::sum[rt[k]]*alpha
}void query(int k,int l,int
r)
if(l<=temp+1&&r>=temp+1
)pos.push_back(val[k]);
if(r<=temp)query(lc[k],l,r);
else
if(l>temp+1)query(rc[k],l-temp-1,r-temp-1
);
else
}int ask(int l,int r,int
k)
else
}ve.clear(),pos.clear();
return
l; }
}int
main()
else
if(opt[0]=='i'
)
else
}return0;
}
bzoj3065帶插入區間K小值
這題其實好像很難,但是聽werkeytom ftd說可以用塊鏈水,於是就很開心地去打了個塊狀鍊錶套主席樹,插入操作就直接插到乙個塊中,注意如果塊的大小2 block就將塊分開,注意每乙個修改或插入都要修改後繼的狀態,貼 include include include include include ...
BZOJ 3065 帶插入區間K小值
思路 做法比較多,我寫的是權值線段樹套平衡樹,平衡樹內維護該權值區間內各元素位置,每次查詢從線段樹根結點開始左右走就可以了。現在問題是如何解決帶插入的情況下快速比較兩個位置標號的前後關係,我們可以用替罪羊樹維護,我們給每個位置標號定個rank區間,例如根定為 0,1e18 定其rank值為中點5 1...
BZOJ3065 替罪羊樹套線段樹
以前看到這題都瑟瑟發抖,終於過了心情舒暢。按下標為關鍵字建替罪羊樹,每個結點開乙個權值線段樹,維護的這個結點代表的子樹的資訊。這題還得垃圾 自己yy的,不知對不對.include include using namespace std define m l r 1 define l x t x s ...