看到題目即可想到使用lct
然而我們發現,只維護點之間的關係是不行的,因為圖上可能會構成環
因此我們將邊雙縮點,發現縮完點後原圖變成了森林
因此就可以直接用lct做了
接下來,我們考慮如何在邊雙縮點的同時維護lct
首先,我們對於每乙個點都要再維護該點所在邊雙的權值和
另外,lct的操作中,凡是涉及到父節點的,都必須要訪問父節點所在的邊雙
因此,對於操作1,如果兩個點當前不處於乙個連通塊中,就把他們link起來
否則的話,就把他們丟到乙個邊雙中,具體操作就是先將 \(x\) 到 \(y\) 的路徑split出來,修改完y的資訊後,再讓路徑上所有的節點都歸入到 \(y\) 的邊雙中
對於修改的話,直接將 \(x\) splay上來,再直接修改資訊即可,但需要注意的是修改資訊時**需要使用邊雙,**不需要
對於查詢的話,如果不在同一連通塊中輸出-1,否則split出來後直接輸出
然而,使用findroot查詢連通塊效率太低,因此我們在儲存邊雙的並查集外再開了乙個並查集用於判連通性
**如下
#include #include #include using namespace std;
const int n = 150000 + 10;
struct node nod[n];
int fa[n];
int find(int x)
int fa2[n];
int find2(int x)
inline void pushup(int x)
inline void pushdown(int x)
}inline int type(int x)
inline void rotate(int x)
nod[x].p=z;
nod[y].ch[typo] = nod[x].ch[typo^1], nod[nod[x].ch[typo^1]].p = y;
nod[x].ch[typo^1] = y;
nod[y].p=x;
pushup(y);
pushup(x);
}inline void down(int x)
inline void splay(int x)
rotate(x); }}
inline void access(int x)
}inline void makeroot(int x)
inline int findroot(int x)
inline void split(int x,int y)
inline void link(int x,int y)
inline void dfs(int x,int y)
int n, q, op, x, y;
int main()
while (q--) else
} if (op == 2)
if (op == 3) else
}// for(int i=1; i<=n; i++)
}}
bzoj2959 動態樹 長跑
2959 長跑 time limit 10 sec memory limit 256 mb submit 807 solved 408 submit status discuss description 某校開展了同學們喜聞樂見的陽光長跑活動。為了能 為祖國健康工作五十年 同學們紛紛離開寢室,離開教...
BZOJ 2959 長跑 解題報告
某校開展了同學們喜聞樂見的陽光長跑活動。為了能 為祖國健康工作五十年 同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加3000公尺長跑運動。一時間操場上熙熙攘攘,摩肩接踵,盛況空前。為了讓同學們更好地監督自己,學校推行了刷卡機制。學校中有n個地點,用1到n的整數表示,每個地點設有若干個刷卡機。有...
刷題 BZOJ 2959 長跑
某校開展了同學們喜聞樂見的陽光長跑活動。為了能 為祖國健康工作五十年 同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加3000公尺長跑運動。一時間操場上熙熙攘攘,摩肩接踵,盛況空前。為了讓同學們更好地監督自己,學校推行了刷卡機制。學校中有n個地點,用1到n的整數表示,每個地點設有若干個刷卡機。有...