K大數查詢 ZJOI2013

2022-05-27 11:33:08 字數 1360 閱讀 8713

【題目描述】

你需要維護 \(n\) 個可重整數集,集合的編號從 \(1\) 到 \(n\)。

這些集合初始都是空集,有 \(m\) 個操作:

【輸入/輸出格式】

不關心\(1 \le n,m \le 5\times 10^4\), \(1\le l,r \le n\), \(1\) 操作中 \(|c|\le n\), \(2\) 操作中 \(1\le c < 2^\)

暴力樹套樹

外層維護權值線段樹 內層是區間修改線段樹

每次修改就把包含\(c\)的那些權值線段樹節點上的 每個內層線段樹的\([l,r]\)區間\(+1\)

查詢就在權值線段樹上二分。。。

雖然要區間修改 但是空間其實是不會爆的 一次修改其實最多會新建\(\log^2 n\)個內層線段樹節點(並不會證明)

時間複雜度似乎是\(o(m\log^2 n)\)

p.s. \(c\)可能是負數 注意要加乙個偏移量

#include using namespace std;

inline int read()

int n, m;

//內層線段樹

struct tree tr[15000005];

int tot;

inline void add(int ind, int l, int r, int v)

inline void pushdown(int ind, int l, int r)

void update(int &ind, int l, int r, int x, int y)

pushdown(ind, l, r);

int mid = (l + r) >> 1;

if (x <= mid) update(tr[ind].lc, l, mid, x, y);

if (mid < y) update(tr[ind].rc, mid+1, r, x, y);

tr[ind].sum = (tr[tr[ind].lc].sum + tr[tr[ind].rc].sum);

}int query(int ind, int l, int r, int x, int y)

//外層線段樹

struct tree tr[200005];

int rt, tot, rt[200005];

void update(int &ind, int l, int r, int x, int y, int pos)

int query(int ind, int l, int r, int x, int y, int k)

int main() else

} return 0;

}

BZOJ K大數查詢(分治)(Zjoi2013)

有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c 如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。第一行n,m 接下來m行,每行形如1 a b c或2 a b c 輸出每個詢問的結果 題目大意 略。思...

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 並且他們的答案 加...