權值線段樹

2022-06-27 05:09:09 字數 1954 閱讀 4274

權值線段樹,每個葉子結點都視為點的權值,在進行操作時要離散

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:

1. 插入x數

2. 刪除x數(若有多個相同的數,因只刪除乙個)

3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)

4. 查詢排名為x的數

5. 求x的前驅(前驅定義為小於x,且最大的數)

6. 求x的後繼(後繼定義為大於x,且最小的數)

input

第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)

output

對於操作3,4,5,6每行輸出乙個數,表示對應答案

sample input

101 106465

4 11 317721

1 460929

1 644985

1 84185

1 89851

6 81968

1 492737

5 493598

sample output

106465

84185

492737

hint

1.n的資料範圍:n<=100000

2.每個數的資料範圍:[-2e9,2e9]

**示例 :

#define ll long long

const ll maxn = 1e5+5;

const ll mod = 1e9+7;

const double eps = 1e-9;

const double pi = acos(-1.0);

const ll inf = 0x3f3f3f3f;

#define lson k<<1

#define rson k<<1|1

struct pp

pre[maxn];

ll s[maxn];

ll k = 1;

struct node

t[maxn<<2];

void build(ll l, ll r, ll k)

void pushup(ll k)

void update(ll pos, ll pt, ll k)

ll m = (t[k].l+t[k].r)>>1;

if (pos <= m) update(pos, pt, lson);

else update(pos, pt, rson);

pushup(k);

}ll ans = 0;

void query3(ll l, ll r, ll k)

ll m = (t[k].l+t[k].r)>>1;

if (l <= m) query3(l, r, lson);

if (r > m) query3(l, r, rson);

}void query4(ll x, ll k)

ll m = (t[k].l+t[k].r)>>1;

if (t[lson].num >= x) query4(x, lson);

else query4(x-t[lson].num, rson);

}int main()

sort(s+1, s+k);

k = unique(s+1, s+k)-s;

//for(int i = 1; i < k; i++) printf("%lld ", s[i]);

build(1, n, 1);

for(ll i = 1; i <= n; i++)

else if (pre[i].pt == 2)

else if (pre[i].pt == 3)

else if (pre[i].pt == 4)

else if (pre[i].pt == 5)

else

}return 0;

}

權值線段樹

維護全域性的值域資訊,每個節點記錄的是該值域的值出現的總次數。使用二分的思想 離散化的時候,需要用到 支援查詢全域性k小值,全域性rank,前驅,後繼等。單詞操作時間複雜度為o logn 空間複雜度為o n 相對於平衡樹的優勢 簡單,速度快 劣勢 值域較大時,我們需要離散化,變成離線資料結構 我認為...

權值線段樹

include using namespace std int n,m,tre 10003 4 laz 10003 4 void pushdown int num void update int num,int le,int ri,int x,int y,int z pushdown num int...

權值線段樹

權值線段樹是線段樹的一種,但是它與線段樹不同 線段樹的每個結點是用來維護一段區間的最大值或總和 而權值線段樹的每個結點儲存的一段區間有多少個數 權值線段樹主要用來查詢區間第k大或者第k小的值 現在有乙個陣列x 10 對陣列排序後為x 10 每個數的個數如下 1 32 2 3 24 1 5 18 1 ...