bzoj2733 永無鄉 平衡樹按秩合併

2022-03-27 02:32:28 字數 1454 閱讀 3178

題意:動態連邊,求出某個聯通塊中權值第$k$小的點。

首先,看到名次果斷想平衡樹……查詢這個問題很好解決,但是合併……恐怕只能暴力修改了吧……

這時候我們需要乙個**:啟發式合併,通俗的講就是小的插到大的裡面去突然汙了起來。我們可以想象一下,如果把大的那棵樹合併到小的那棵去,那麼每個節點暴力合併……時間代價不堪設想……因此按秩合併可以有效減短合併時間……然後就是暴力插點刪點就行了……

1 #include2 #include3 #include4 #include5

#define lc(x) ((x)->ch[0])

6#define rc(x) ((x)->ch[1])

7#define size(x) ((x)?(x->siz):0)

8using

namespace

std;

9const

int maxn=100005;10

intn,m;

11struct

node

1216 node(int v=0,int d=0):val(v),fix(rand()),id(d),siz(1)

17void maintain()

18};

19struct

treap

2027

void insert(node* &rt,int x,int

y)28

30int d=rt->val>x;insert(rt->ch[d^1],x,y);rt->maintain();

31if(rt->ch[d^1]->fixfix)rotate(rt,d);

32 rt->maintain();33}

34void del(node* &rt,int

x)35

43else

4449}50

else

5156}57

int rank(node *rt,int

x)58

65int kth(node *rt,int

x)66

73return -1;74

}75void mergeto(node* src,node* &to)

7682

}t;83

intf[maxn];

84int getfa(int

x)85

88void unionn(int x,int

y)8996}

97int

a[maxn];

98int

haha()

99107

int q;scanf("

%d",&q);

108for(int i=1;i<=q;i++)

109114

}115

int sb=haha();

116int main()

bzoj2733

bzoj2733 永無鄉 線段樹合併

這道題是一道經典的平衡樹 啟發式合併吧。那麼考慮用可持久化線段樹來寫。對每乙個節點儲存一棵線段樹表示所在塊的編號的集合 因此可以乙個塊值儲存一棵樹 然後合併的時候就地櫃合併左子節點和右子節點,然後更新節點的值即可。時空複雜度o nlogn ac 如下 include include include ...

BZOJ 2733 永無鄉 線段樹合併

time limit 10 sec memory limit 128 mb submit 3624 solved 1937 submit status discuss 永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n ...

BZOJ2733 永無鄉 線段樹合併

永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連線,通過橋可以從乙個島 到達另乙個島。如果從島 a 出發經過若干座 含 0 座 橋可以到達島 b,則稱島 a 和島 b 是連 通的。現在有...