洛谷P3380 模板 二逼平衡樹(樹套樹)

2021-09-08 14:08:52 字數 3657 閱讀 7987

查詢k在區間內的排名

查詢區間內排名為k的值

修改某一位值上的數值

查詢k在區間內的前驅(前驅定義為嚴格小於x,且最大的數,若不存在輸出-2147483647)

查詢k在區間內的後繼(後繼定義為嚴格大於x,且最小的數,若不存在輸出2147483647)

輸入格式:

第一行兩個數 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各輸出一行,表示查詢結果

輸入樣例#1: 

複製

9 6

4 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 5

輸出樣例#1: 

複製

243

49

時空限制:2s,128m

n,m \leq 5\cdot ^4n,m≤5⋅104 保證有序序列所有值在任何時刻滿足 [0, ^8][0,108]

複習了一下樹套樹

感覺很套路啊qwq,

然而不想重寫, 所以就對著以前的抄了一遍。

//

luogu-judger-enable-o2

#include#include

#include

#include

using

namespace

std;

const

int maxn = 2000001

;inline

intread()

while(c >= '

0' && c <= '9')

return x *f;

}#define ls(k) s[k].ch[0]

#define rs(k) s[k].ch[1]

struct

sp s[maxn];

intsz;

inline

void pushup(int k)

inline

int ident(int x)

inline

void connect(int x, int f, int

how)

inline

void rotate(int &root,int x)

inline

void splay(int &root, int x, int to)

}inline

void insert(int &k, int c)

if(s[k].num==c) s[k].rev++;

else

if(s[k].num < c) insert(rs(k), c), s[rs(k)].fa =k;

else insert(ls(k), c), s[ls(k)].fa =k;

pushup(k);

}inline

int getpre(int k,int val)

return

ret;

}inline

int getsuc(int k,int

val)

return

ret;

}inline

int getk(int k,int

val)

#define ls k << 1

#define rs k << 1 | 1

struct

node t[maxn];

inline

void pushup_s(int k)

inline

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

inline

void delet(int &k, int val)

else

}inline

void build(int k, int pos, int x)

int mid = (t[k].l + t[k].r) >> 1

;

if(pos <=mid) build(ls, pos, x);

if(pos >mid) build(rs, pos, x);

pushup_s(k);

//別忘了上傳線段樹標記

}int newnode(int val, int

f) inline

void dfsseg(int k)

inline

int getmax(int k,int l,int r)

inline

int getmin(int k,int l,int r)

inline

int query_order(int k, int l, int r, int val)

int mid = (t[k].l + t[k].r) >> 1, ret = 0

;

if(l <= mid) ret +=query_order(ls, l, r, val);

if(r > mid) ret +=query_order(rs, l, r, val);

return

ret;

}inline

void modify(int k,int pos,int pre,int now)

int mid = (t[k].l + t[k].r) >> 1

;

if(pos <=mid) modify(ls , pos, pre, now);

if(pos >mid) modify(rs , pos, pre, now);

pushup_s(k);

//別忘了上傳標記!

}inline

int query_pre(int k,int l,int r,int val)

inline

int query_suc(int k,int l,int r,int val)

inline

int querynum(int l,int r,int val)

return

ret;

}int

n, m;

intdate[maxn];

intmain()

if(opt == 2)

if(opt==3)

if(opt==4

)

if(opt == 5

) }

return0;

}

洛谷P3380 模板 二逼平衡樹(樹套樹)

查詢k在區間內的排名 查詢區間內排名為k的值 修改某一位值上的數值 查詢k在區間內的前驅 前驅定義為嚴格小於x,且最大的數,若不存在輸出 2147483647 查詢k在區間內的後繼 後繼定義為嚴格大於x,且最小的數,若不存在輸出2147483647 輸入格式 第一行兩個數 n,m 表示長度為n的有序...

洛谷P3380 模板 二逼平衡樹(樹套樹)

查詢k在區間內的排名 查詢區間內排名為k的值 修改某一位值上的數值 查詢k在區間內的前驅 前驅定義為嚴格小於x,且最大的數,若不存在輸出 2147483647 查詢k在區間內的後繼 後繼定義為嚴格大於x,且最小的數,若不存在輸出2147483647 輸入格式 第一行兩個數 n,m 表示長度為n的有序...

洛谷 P3380 模板 二逼平衡樹(樹套樹)

其實比想象中的好理解啊 所謂樹套樹,就是在一棵樹的基礎上,每乙個節點再維護一棵樹 說白了,就是為了實現自己想要的操作和優秀的時間複雜度,來人為的增加一些毒瘤資料結構來維護一些什麼東西 比如說這道題 如果只求乙個區間內的乙個數是否是最大值或者最小值,我們顯然可以用線段樹輕輕鬆鬆地解決這個問題 但是現在...