題解 P3332 ZJOI2013 K大數查詢

2022-06-20 10:18:12 字數 2112 閱讀 6371

link

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

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

\(1 \leq n ,m \leq 10^5 ,1 \leq c \leq 2^\) 。

發現插入,查詢 \(k\) 大,考慮線段樹套平衡樹。

但是發現 \(n ,m \leq 10^5\) ,並且區間插入並不好打懶標記,比較麻煩。

並且因為平衡樹極其優秀的常數,很容易 tle 。

所以考慮轉換思路:我們用權值線段樹套動態開店線段樹。

權值線段樹維護所有權值,裡面那一層線段樹維護所有權值在下標內出現的次數。

對於1操作,我們先在外層線段樹找到權值為 \(c\) 的節點,然後在經過的所有節點對應的內層線段樹上讓區間 \([l,r]\) 加上一,表示這些位置多了乙個數。

對於2操作,假如我們當前在權值線段樹上的節點是 \(now\) 。我們可以看一下 \(now\) 的右兒子落在下標 \([l,r]\) 範圍內有幾個數(就是在右兒子對應的裡層線段樹中查詢 \([l,r]\) 的和)。如果個數 \(\geq c\) ,那麼 \(c\) 大一定在右子樹里,遞迴右兒子處理。

否則 \(c\) 大在左兒子的子樹裡,遞迴左子樹。注意遞迴左子樹的時候需要將 \(c\) 減掉右兒子 \([l,r]\) 內的數的個數(就像平衡樹查排名對應的值一樣)。

另外,注意到 \(c \leq 2^\) ,所以我們要先讀進所有的操作,然後把所有插入的數放在一起離散化。

**如下:

#include #include #include #include #define int long long

using namespace std;

inline int read()

inline int min(int a ,int b)

inline int max(int a ,int b)

inline void swap(int &a ,int &b)

const int n = 5e4 + 5;

struct segment1

}t[n * 17 * 17]; int tot; //空間記得開夠

segment1() : tot(0) {}

inline void update(int &now)

inline void puttag(int &now ,int l ,int r ,int k)

inline void pushdown(int &now ,int l ,int r)

inline void modify(int &now ,int l ,int r ,int ql ,int qr ,int k)

pushdown(now ,l ,r);

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

if (ql <= mid) modify(t[now].l ,l ,mid ,ql ,qr ,k);

if (qr > mid) modify(t[now].r ,mid + 1 ,r ,ql ,qr ,k);

update(now);

}inline int query(int &now ,int l ,int r ,int ql ,int qr)

}u;int n;

struct segment

inline void join(int now ,int l ,int r ,int ql ,int qr ,int k)

inline int query(int now ,int l ,int r ,int ql ,int qr ,int k)

}t;int m ,nums[n] ,tot;

inline int find(int val)

struct opts

}q[n];

signed main()

sort(nums + 1 ,nums + tot + 1);

tot = unique(nums + 1 ,nums + tot + 1) - nums - 1;

for (int i = 1; i <= m; i++)

return 0;

}

P3332 ZJOI2013 K大數查詢

有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 輸出格式 輸出每個詢問的結果 ...

洛谷 P3332 ZJOI2013 K大數查詢

題目 k大數查詢 思路 整體二分。維護兩個區間 l,r 和 l,r 分別代表二分的答案區間,和可以滿足答案的詢問區間。在 l,r 上二分m。對於1操作,如果v小於m,在 q.l,q.r 上用線段樹實現區間加一,值賦1,否則賦0。對於2操作,詢問 q.l,q.r 上的數的個數s,若v小於等於s,值賦1...

洛谷P3332 ZJOI2013 K大數查詢

description 帶區間修求區間第kkk大 資料範圍 n 5 104 n leq 5 times 10 4 n 5 104so luti on solution soluti on字首和套主席樹可以解決靜態 樹狀陣列套主席樹可以解決單點修改區間查詢 貌似在這道題,外層套乙個可以區間修改區間查詢...