題面
bzoj3196
解析線段樹和splay兩棵樹套在一起,常數直逼inf,但最終僥倖過了
思路還是比較簡單, 在原陣列維護乙個下標線段樹,再在每乙個線段樹節點,維護乙個對應區間的權值splay。簡單說一下操作:
0.提取區間
1.查詢區間內k的排名
提取區間,找到區間內所有的splay, 分別比k小的數的個數,相加後加一即可
2.查詢區間第k大
提取區間,找到區間內所有的splay,因為有多棵splay,這個操作顯然不能像一般的splay一樣查詢,只能二分答案,轉化為操作一,再check排名就行
3.單點修改
4.求前驅
同樣找到區間內的所有splay,分別進入找前驅,輸出最大的前驅即可。但k可能不在splay中,於是我們先要找到大於等於k的權值最小的節點,將它旋轉到根,再找前驅,但由於可能沒有前驅,就在每棵splay插入-inf, 查詢排名時記得減去即可
5.求後繼
操作與前驅類似,找到小於等於k的權值最大的節點,旋轉到根,找後繼,記得每棵splay插入inf就行
大部分操作都是自己yy的,可能不是很優秀,但我這個又臭又長的**並沒有除錯多久,也是不容易啊。
**(340行):
#includeusingview codenamespace
std;
const
int maxn = 100005, inf = 2147483647
;template
void read(t &re)
int n, m, root[maxn<<1
], rt, a[maxn];
int tot, cnt, lson[maxn<<1], rson[maxn<<1
], stak[maxn], top, s[maxn], snum;
struct
splay_treetr[maxn * 20
];void update(int
x)void rotate(int
x)void splay(int x, int to, int
id)
if(!to)
root[id] =x;
}void insert(int x, int
v)
if(now)
tr[now].num ++;
else
splay(now,
0, x);
}void build(int &x, int l, int
r)void extract(int x, int l, int r, int l, int
r)
int mid = (l + r)>>1
;
if(l <=mid)
extract(lson[x], l, r, l, mid);
if(mid
extract(rson[x], l, r, mid + 1
, r);
}int queryrk(int id, int
x)
else
if(x ==tr[now].val)
else
}tr[
0].s[1] =root[id];
splay(now,
0, id);
return
ret;
}int work1(int
x)
return ret + 1;}
int check(int
x)int work2(int
x) top = 0
;
return
ret;
}int find(int now, intx)}
int querypre(int
now)
int querynxt(int
now)
void modify(int x, int pos, int l, int r, int
v)
else
update(nxt);update(pre);
insert(x, v);
if(l ==r)
int mid = (l + r)>>1
;
if(pos <=mid)
modify(lson[x], pos, l, mid, v);
else
modify(rson[x], pos, mid + 1
, r, v);
}int findmx(int now, int
x)
else
now =rs;
}return
ret;
}int findmn(int now, int
x)
else
now =ls;
}return
ret;
}int work3(int
x)
return
ret;
}int work4(int
x)
return
ret;
}int
main()
else
if(opt == 2
)
else
if(opt == 3
)
else
if(opt == 4
)
else
}return0;
}
BZOJ3196 二逼平衡樹 線段樹套Splay
您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 第一行兩個數 n,m 表示長...
bzoj3196 二逼平衡樹 線段樹套平衡樹
題目描述 寫一種資料結構,來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 輸入格式 第一行兩個數n,m n,m 5...
樹套樹 線段樹套set
請你寫出一種資料結構,來維護乙個長度為 n 的序列,其中需要提供以下操作 1 pos x,將 pos 位置的數修改為 x。2 l r x,查詢整數 x 在區間 l,r 內的前驅 前驅定義為小於 x,且最大的數 數列中的位置從左到右依次標號為 1 n。區間 l,r 表示從位置 l 到位置 r 之間 包...