3196 Tyvj 1730 二逼平衡樹

2021-07-17 04:00:31 字數 3271 閱讀 5097

time limit: 10 sec  

memory limit: 128 mb

submit: 2771  

solved: 1121 [

submit][

status][

discuss]

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

1.查詢k在區間內的排名

2.查詢區間內排名為k的值

3.修改某一位值上的數值

4.查詢k在區間內的前驅(前驅定義為小於x,且最大的數)

5.查詢k在區間內的後繼(後繼定義為大於x,且最小的數)

第一行兩個數 n,m 表示長度為n的有序序列和m個操作

第二行有n個數,表示有序序列

下面有m行,opt表示操作標號

若opt=1 則為操作1,之後有三個數l,r,k 表示查詢k在區間[l,r]的排名

若opt=2 則為操作2,之後有三個數l,r,k 表示查詢區間[l,r]內排名為k的數

若opt=3 則為操作3,之後有兩個數pos,k 表示將pos位置的數修改為k

若opt=4 則為操作4,之後有三個數l,r,k 表示查詢區間[l,r]內k的前驅

若opt=5 則為操作5,之後有三個數l,r,k 表示查詢區間[l,r]內k的後繼

對於操作1,2,4,5各輸出一行,表示查詢結果

9 64 2 2 1 9 4 0 1 1

2 1 4 3

3 4 10

2 1 4 3

1 2 5 9

4 3 9 5

5 2 8 524

3491.n和m的資料範圍:n,m<=50000

2.序列中每個數的資料範圍:[0,1e8]

3.雖然原題沒有,但事實上5操作的k可能為負數

[submit][

status][

discuss]

首先,,這個必須樹套樹

苟蒻首先想到的是樹狀陣列套線段樹,不過苟蒻的寫法略吃記憶體,mle

然後,,線段樹套treap可以解決記憶體問題

但是套treap造成常數巨大,,,tle

現在就是寫法的問題,,,

首先,插入和刪除操作用指標,快一些

然後treap的每個點可以不僅僅只存乙個元素,可以存多個

w[x]代表這個元素在這個點重複多少次

這樣可以省去max和min陣列的維護

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 5e4 + 50;

const int inf = ~0u>>1;

const int t = 25;

typedef unsigned short us;

int n,m,cnt,ch[maxn*t][2],num[maxn],va[maxn*t],l[maxn],r[maxn]

,k[maxn],num[maxn*2],key[maxn*t],root[maxn*4];

us typ[maxn],siz[maxn*t],w[maxn*t];

int getint()

while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar();

return ret*multi;

}int new(int num)

void maintain(int x)

void rotate(int &x,int d)

void insert(int &x,int num)

if (num == va[x])

if (va[x] < num)

else

maintain(x);

}void insert(int o,int l,int r,int pos,int num)

int sum(int x,int po)

int sum(int o,int l,int r,int ql,int qr,int po)

void remove(int &x,int num)

if (!ch[x][0] && !ch[x][1])

if (!ch[x][0] || !ch[x][1])

if (key[ch[x][0]] > key[ch[x][1]])

else

maintain(x); return;

} if (va[x] < num)

else

maintain(x);

}void remove(int o,int l,int r,int pos,int num,int num2)

int pre(int x,int k)

int pre(int o,int l,int r,int ql,int qr,int k)

int nex(int x,int k)

int nex(int o,int l,int r,int ql,int qr,int k)

int nu;

char c[20];

void print( int k )

int main()

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

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

for (int i = 2; i <= tot; i++)

if (num[i] != num[i-1])

num[++cur] = num[i];

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

else if (typ[i] == 2)

if (sum(1,1,n,l,r,num[ll]) >= k) print(num[ll]);

else print(num[rr]);

} else if (typ[i] == 3)

else if (typ[i] == 4)

else

} return 0;

}

3196 Tyvj 1730 二逼平衡樹

分析 帶區間查詢和名次詢問,線段樹套treap 操作1 查詢k在區間內的排名。求出k 1的名次 1就是k的名次 操作2 查詢區間內排名為k的值。二分列舉權值,呼叫操作1 操作3 修改某一位值上的數值。在樹上先刪除,再插入 操作4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 操作5.查詢k在區...

3196 Tyvj 1730 二逼平衡樹

題目比較簡潔 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 又有區間,又有...

BZOJ3196 Tyvj 1730 二逼平衡樹

description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 in...