題意:動態連邊,求出某個聯通塊中權值第$k$小的點。
首先,看到名次果斷想平衡樹……查詢這個問題很好解決,但是合併……恐怕只能暴力修改了吧……
這時候我們需要乙個**:啟發式合併,通俗的講就是小的插到大的裡面去突然汙了起來。我們可以想象一下,如果把大的那棵樹合併到小的那棵去,那麼每個節點暴力合併……時間代價不堪設想……因此按秩合併可以有效減短合併時間……然後就是暴力插點刪點就行了……
1 #include2 #include3 #include4 #include5bzoj2733#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 永無鄉 線段樹合併
這道題是一道經典的平衡樹 啟發式合併吧。那麼考慮用可持久化線段樹來寫。對每乙個節點儲存一棵線段樹表示所在塊的編號的集合 因此可以乙個塊值儲存一棵樹 然後合併的時候就地櫃合併左子節點和右子節點,然後更新節點的值即可。時空複雜度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 是連 通的。現在有...