BZOJ 2959 長跑 LCT 並查集

2021-09-27 06:32:56 字數 1529 閱讀 7571

真是被這題搞得心態大崩……調了7個小時……然而並查集都能寫成\(o(n^2)\)的我還能怪誰呢

顯然要把每個邊雙連通分量縮成點,點權為邊雙連通分量內所有點點權和,然後答案就等於兩點路徑上點權和

現在需要用lct維護,就比較麻煩

大概是一邊lct一邊使用並查集分別維護連通塊和邊雙連通分量

加邊時,若兩點不聯通,則link, 然後在維護連通塊的並查集裡並起來

若兩點聯通但不在同一邊雙中,則把這兩個點路徑上的所有邊雙縮到一起(其實就是「刪除點」),順便加入到邊雙連通分量的並查集中

這個可以通過把路徑的splay提取出來進行dfs實現,因為每個點只會被刪一次所以複雜度正確

但是這裡由於縮點,我們每次在lct中訪問父親的時候要求它樹上父親在並查集裡的代表元素。。。所以很容易寫錯

時間複雜度\(o(n\log n\alpha(n))\).

#include#include#include#include#include#define llong long long

using namespace std;

const int n = 1.5e5;

struct splaynode

spl[n+3];

int uf1[n+3],uf2[n+3];

int stk[n+3];

int a[n+3];

int n,q;

inline int read()

int findfa(int id,int u)

while(uf1[i]!=u)

}else

while(uf2[i]!=u)

}return u;

}bool isroot(int u)

bool sondir(int u)

void pushup(int u)

void pushdown(int u)

if(rs)

}}void rotate(int u)

spl[u].fa = y;

spl[x].son[dir^1] = spl[u].son[dir];

if(spl[x].son[dir^1])

spl[u].son[dir] = x; spl[x].fa = u;

pushup(x);

}void splaynode(int u)

pushdown(x);

while(tp)

while(!isroot(u))

rotate(u);

}pushup(u);

}void access(int u)

}void makeroot(int u)

void link(int u,int v)

void dfs(int u,int u0)

int main()

else

}else if(opt==2)

else if(opt==3)

else}}

return 0;

}

bzoj 2959 長跑(LCT 並查集)

time limit 10 sec memory limit 256 mb submit 315 solved 178 submit status discuss 某校開展了同學們喜聞樂見的陽光長跑活動。為了能 為祖國健康工作五十年 同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加3000公尺長...

BZOJ2959 長跑(lct 並查集)

傳送門 用lct維護一顆動態樹。如果連了某一條邊形成了乙個環,證明一次長跑這個環上的所有的點都可以被統計,所以可以將這個環縮成乙個點。用ufs來實現。那麼一次長跑實際上就是在一條樹鏈上跑,只有乙個方向,在lct上維護乙個sum就可以了。時間複雜度是均攤的,因為每乙個點至多被縮點一次,所以o k ml...

bzoj2959 長跑 LCT 並查集

某校開展了同學們喜聞樂見的陽光長跑活動。為了能 為祖國健康工作五十年 同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加3000公尺長跑運動。一時間操場上熙熙攘攘,摩肩接踵,盛況空前。為了讓同學們更好地監督自己,學校推行了刷卡機制。學校中有n個地點,用1到n的整數表示,每個地點設有若干個刷卡機。有...