bzoj2959 長跑 LCT 並查集

2022-05-20 10:11:25 字數 2712 閱讀 9048

題目描述

某校開展了同學們喜聞樂見的陽光長跑活動。為了能「為祖國健康工作五十年」,同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加3000公尺長跑運動。一時間操場上熙熙攘攘,摩肩接踵,盛況空前。

為了讓同學們更好地監督自己,學校推行了刷卡機制。

學校中有n個地點,用1到n的整數表示,每個地點設有若干個刷卡機。

有以下三類事件:

1、修建了一條連線a地點和b地點的跑道。

2、a點的刷卡機台數變為了b。

3、進行了一次長跑。問乙個同學從a出發,最後到達b最多可以刷卡多少次。具體的要求如下:

當同學到達乙個地點時,他可以在這裡的每一台刷卡機上都刷卡。但每台刷卡機只能刷卡一次,即使多次到達同一地點也不能多次刷卡。

為了安全起見,每條跑道都需要設定乙個方向,這條跑道只能按照這個方向單向通行。最多的刷卡次數即為在任意設定跑道方向,按照任意路徑從a地點到b地點能刷卡的最多次數。

輸入輸入的第一行包含兩個正整數n,m,表示地點的個數和操作的個數。

第二行包含n個非負整數,其中第i個數為第個地點最開始刷卡機的台數。

接下來有m行,每行包含三個非負整數p,a,b,p為事件型別,a,b為事件的兩個引數。

最初所有地點之間都沒有跑道。

每行相鄰的兩個數之間均用乙個空格隔開。表示地點編號的數均在1到n之間,每個地點的刷卡機台數始終不超過10000,p=1,2,3。

輸出輸出的行數等於第3類事件的個數,每行表示乙個第3類事件。如果該情況下存在一種設定跑道方向的方案和路徑的方案,可以到達,則輸出最多可以刷卡的次數。如果a不能到達b,則輸出-1。

樣例輸入

9 31

10 20 30 40 50 60 70 80 90

3 1 2

1 1 3

1 1 2

1 8 9

1 2 4

1 2 5

1 4 6

1 4 7

3 1 8

3 8 8

1 8 9

3 8 8

3 7 5

3 7 3

1 4 1

3 7 5

3 7 3

1 5 7

3 6 5

3 3 6

1 2 4

1 5 5

3 3 6

2 8 180

3 8 8

2 9 190

3 9 9

2 5 150

3 3 6

2 1 210

3 3 6

樣例輸出

-1-1

80170

180170

190170

250280

280270

370380

580題解

lct+並查集

首先考慮答案是什麼:如果圖是乙個森林的話,那麼答案顯然是兩點之間路徑上的點權之和。

如果不是森林的話,考慮把每個邊雙縮成乙個點,只要到達這個邊雙各種的任意乙個點即可全部到達。所以答案為兩點之間路徑上所有邊雙的點權之和。

所以只需要動態維護邊雙即可。

考慮到沒有刪除操作,所以可以使用並查集維護每個點所在的邊雙。同時使用lct維護樹的形態結構。

具體地,對於每個加邊操作,如果它們不在同乙個邊雙里且未連通,則把它們所在邊雙連上。否則如果它們不在同乙個邊雙里且已經連通,則需要提取它們之間的路徑,把路徑上的點所在邊雙全部改為新的邊雙並在lct中「刪除」這些點。這個過程可以直接對splay tree進行dfs實現,並使用並查集來維護。

同時因為使用並查集「刪點」,所以在查詢父親時需要在並查集中find。

修改和查詢操作和普通的lct相同。

總的時間複雜度為常數巨大的$o((n+m)\log n)$。親測必須使用並查集維護森林的連通性而非lct中的findroot函式,以及加上讀入優化才可以過(出題人卡常數喪心病狂= =)

#include #include #include #define n 150010

using namespace std;

int v[n] , f[n] , fa[n] , c[2][n] , w[n] , sum[n] , rev[n] , con[n];

int find(int x)

int fc(int x)

void pushup(int x)

void pushdown(int x)

bool isroot(int x)

void update(int x)

void rotate(int x)

void splay(int x)

}void access(int x)

void makeroot(int x)

void link(int x , int y)

void split(int x , int y)

void cut(int x , int y)

void dfs(int x , int y)

inline int read()

int main()

}else if(opt == 2) splay(tx) , w[tx] += y - v[x] , sum[tx] += y - v[x] , v[x] = y;

else if(fc(tx) != fc(ty)) puts("-1");

else split(tx , ty) , printf("%d\n" , sum[ty]);

}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的整數表示,每個地點設有若干個刷卡機。有...