ZJOI2013 K大數查詢

2022-05-15 13:48:08 字數 1064 閱讀 5745

目錄曾經光輝無限的省選題......

竟然是二刷。

傳送門 to luogu

先考慮對於單個詢問,我們只需要二分答案,然後看一下比這個答案大的數有多少即可。

然後我們將所有詢問用整體二分來做,處理到當前值域區間 \([l,r]\),也就相當於我們二分了乙個 \(mid\),對於這個 \(mid\),將所有操作一中插入值大於 \(mid\) 的操作對應的區間整體加一,對於詢問操作直接查詢即可。

但是需要注意乙個細節 —— 當詢問操作被下放到左區間時,對應查詢的 \(rank\) 應該要減去這一次二分後查詢的結果,這個可以模擬平衡樹。

using namespace elaina;

const int maxn=5e4;

const int maxm=5e4;

const ll maxa=(1ll<<62)-1+(1ll<<62);

namespace tree

inline void clear(const int i)

inline void pushdown(const int i,const int l,const int r)

} inline void pushup(const int i)

void modify(const int l,const int r,const int i,const int l,const int r)

int mid=(l+r)>>1,cntl=0,cntr=0;

tree::clear(1);

for(int i=ql;i<=qr;++i)else tmpl[++cntl]=opt[i];

} else{

ll ret=tree::query(opt[i].l,opt[i].r,1,1,n);

// the value mid is too big

if(ret除了整體二分之外,還用到乙個比較經典的 \(\tt trick\).

先二分乙個值,對於這個值來說,大於它的記為 \(1\),其他看做 \(0\),這樣就將原來參差不齊的陣列變成了 \(01\) 陣列,比起原來的陣列更好處理,如果詢問單點只需要再加上乙個 \(\log\).

ZJOI2013 K大數查詢

有n個位置,m個操作。1 a b c形式,表示在第a個位置到第b個位置,每個位置加入乙個數c 2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。區間的第k大值有一種二分的做法。二分答案mid,計算出區間內 mid的值有多少個。若數量小於c,則ans mid,否則ans mid。...

ZJOI2013 K大數查詢

有n個位置,m個操作。操作有兩種,每次操作如果是 2 a b c 表示詢問從第a個位置到第b個位置,第c大的數是多少。輸入格式 第一行n,m接下來m行,每行形如1 a b c或2 a b c 輸出格式 輸出每個詢問的結果 solution 整體二分。假設我們現在要解決 ql,qr 並且他們的答案 加...

ZJOI2013 K大數查詢

點此看題 0x01 樹套樹 這道題的思路特別巧妙,樹套樹不一定要用區間線段樹套權值線段樹,還可以反過來套。我們維護乙個動態開點的權值線段樹,每個點代表權值 l,r l,r l,r 在整個區間的出現情況,套上乙個動態開點的區間線段樹,操作1 11對權值線段樹單點修改,然後對每個點的 a,b a,b a...