【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息
題目描述
給出一棵樹(shù)和一個(gè)點(diǎn)對(duì)集合S,多次改變這棵樹(shù)的形態(tài)、在集合中加入或刪除點(diǎn)對(duì),或詢(xún)問(wèn)集合內(nèi)的每組點(diǎn)對(duì)之間的路徑是否都經(jīng)過(guò)某條給定邊。
輸入
輸入的第一行包含一個(gè)整數(shù) id,表示測(cè)試數(shù)據(jù)編號(hào),如第一組數(shù)據(jù)的id=1,樣例數(shù)據(jù)的 id 可以忽略。
輸入的第二行包含兩個(gè)整數(shù) n,m,分別表示圖中的點(diǎn)數(shù),以及接下來(lái)會(huì)發(fā)生的事件數(shù),事件的定義下文中會(huì)有描述。初始時(shí) S 為空。
接下來(lái) n?1 行,每行兩個(gè)正整數(shù) x,y,表示點(diǎn) x 和點(diǎn) y 之間有一條無(wú)向邊。
接下來(lái) m 行,每行描述一個(gè)事件,每行的第一個(gè)數(shù) type 表示事件的類(lèi)型。
若type=1,那么接下來(lái)有四個(gè)正整數(shù)x,y,u,v,表示先刪除連接點(diǎn)x和點(diǎn)y的無(wú)向邊,保證存在這樣的無(wú)向邊,然后加入一條連接點(diǎn)u和點(diǎn)v的無(wú)向邊,保證操作后的圖仍然滿(mǎn)足題中所述條件。
若type=2,那么接下來(lái)有兩個(gè)正整數(shù) x,y,表示在 S 中加入點(diǎn)對(duì) (x,y)。
若type=3,那么接下來(lái)有一個(gè)正整數(shù) x,表示刪除第 x 個(gè)加入 S 中的點(diǎn)對(duì),即在第 x 個(gè) type=2 的事件中加入 S 中的點(diǎn)對(duì),保證這個(gè)點(diǎn)對(duì)存在且仍然在 S 中。
若 type=4,那么接下來(lái)有兩個(gè)正整數(shù) x,y,表示小L詢(xún)問(wèn)守在連接點(diǎn) x 和點(diǎn) y 的邊上是否一定能見(jiàn)到共價(jià)大爺,保證存在這樣的無(wú)向邊且此時(shí) S 不為空。
輸出
對(duì)于每個(gè)小L的詢(xún)問(wèn),輸出“YES”或者“NO”(均不含引號(hào))表示小L一定能或者不一定能見(jiàn)到共價(jià)大爺。
樣例輸入
0
5 7
1 2
1 3
2 4
1 5
2 1 5
1 1 5 2 5
4 2 5
2 1 4
4 2 5
3 1
4 2 4
題解
隨機(jī)化+LCT維護(hù)子樹(shù)信息
對(duì)與每個(gè)點(diǎn)對(duì),隨機(jī)一個(gè)權(quán)值,把這個(gè)權(quán)值異或到這兩個(gè)點(diǎn)上。那么對(duì)于查詢(xún),如果 x 為樹(shù)根時(shí),y 子樹(shù)中的所有點(diǎn)的權(quán)值的異或和等于所有點(diǎn)對(duì)的異或和,則視為所有點(diǎn)對(duì)間的路徑都經(jīng)過(guò) x-y 。(別問(wèn)我怎么想出來(lái)的。。。做過(guò)一道類(lèi)似的題)
當(dāng)權(quán)值范圍足夠大時(shí)可以近似視為正確。
由于樹(shù)的形態(tài)是變化的,因此需要使用LCT維護(hù)子樹(shù)信息,具體方法參見(jiàn)這里。
注意維護(hù)子樹(shù)信息的LCT:link時(shí)需要makeroot(x),makeroot(y);修改時(shí)需要makeroot(x)而不是簡(jiǎn)單的splay(x);查詢(xún)時(shí)需要先makeroot(x)。
時(shí)間復(fù)雜度 $O(LCT·n\log n)$?
#include <cstdio> #include <algorithm> #define N 100010 using namespace std; int fa[N] , c[2][N] , rev[N] , w[N] , sum[N] , vx[N * 3] , vy[N * 3] , vw[N * 3] , tot; inline void pushup(int x) {sum[x] = sum[c[0][x]] ^ sum[c[1][x]] ^ w[x]; } inline void pushdown(int x) {if(rev[x]){int l = c[0][x] , r = c[1][x];swap(c[0][l] , c[1][l]) , rev[l] ^= 1;swap(c[0][r] , c[1][r]) , rev[r] ^= 1;rev[x] = 0;} } inline bool isroot(int x) {return c[0][fa[x]] != x && c[1][fa[x]] != x; } void update(int x) {if(!isroot(x)) update(fa[x]);pushdown(x); } inline void rotate(int x) {int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;if(!isroot(y)) c[c[1][z] == y][z] = x;fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;pushup(y) , pushup(x); } inline void splay(int x) {int y , z;update(x);while(!isroot(x)){y = fa[x] , z = fa[y];if(!isroot(y)){if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);else rotate(y);}rotate(x);} } inline void access(int x) {int t = 0;while(x) splay(x) , w[x] ^= sum[c[1][x]] ^ sum[t] , c[1][x] = t , t = x , x = fa[x]; } inline void makeroot(int x) {access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] ^= 1; } inline void link(int x , int y) {makeroot(x) , makeroot(y) , fa[x] = y , w[y] ^= sum[x] , pushup(y); } inline void cut(int x , int y) {makeroot(x) , access(y) , splay(y) , fa[x] = c[0][y] = 0 , pushup(y); } int main() {srand(20011011);int n , m , i , opt , x , y , u , v , now = 0;scanf("%*d%d%d" , &n , &m);for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , link(x , y);while(m -- ){scanf("%d%d" , &opt , &x);if(opt == 1) scanf("%d%d%d" , &y , &u , &v) , cut(x , y) , link(u , v);else if(opt == 2){scanf("%d" , &y);vx[++tot] = x , vy[tot] = y , vw[tot] = (rand() << 15) + rand() , now ^= vw[tot];makeroot(x) , w[x] ^= vw[tot] , pushup(x);makeroot(y) , w[y] ^= vw[tot] , pushup(y);}else if(opt == 3){now ^= vw[x];makeroot(vx[x]) , w[vx[x]] ^= vw[x] , pushup(vx[x]);makeroot(vy[x]) , w[vy[x]] ^= vw[x] , pushup(vy[x]);}else scanf("%d" , &y) , makeroot(x) , access(y) , splay(y) , puts(sum[x] == now ? "YES" : "NO");}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/GXZlegend/p/8244009.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cfe刷机教程 斐讯k3_斐讯K3刷机教
- 下一篇: js打开新窗口与页面跳转