bzoj 2959 長跑(LCT 並查集)

2021-07-25 06:58:42 字數 2777 閱讀 7111

time limit: 10 sec  

memory limit: 256 mb

submit: 315  

solved: 178 [

submit][

status][

discuss]

某校開展了同學們喜聞樂見的陽光長跑活動。為了能「為祖國健康工作五十年」,同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加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資料規模及約定

對於100%的資料,m<=5n,任意時刻,每個地點的刷卡機台數不超過10000。n<=1.5×105

中國國家隊清華集訓 2012-2013 第二天 [

submit][

status][

discuss]

題解:lct+並查集

lct維護雙聯通性。

這道題如果沒有加邊操作,那麼可以用tarjan縮點然後建樹鏈剖。但是加邊的話會使原本構不成環的部分構成新的環所以考慮在樹上用lct進行動態的縮點和維護操作。

如果加入某條邊之前兩個端點就聯通,那麼我們就將兩個點之間的路徑提出來,加入改邊會使這條路徑上的點可以互相到達,所以我們把這些點縮成乙個代表節點,然後將權值都加給這個節點。並用另外乙個並查集維護每個點所屬的代表元素資訊。

對於詢問2,其實就變成了從lct中提取縮點後兩點所屬的點之間的路徑上的權值總和。

寫lct是需要注意,以前找的是fa[x],現在應該是找findset(fa[x]),就是fa[x]所屬的縮點的代表元素。

因為每個點最多隻會被合併一次,所以我們的時間複雜度仍然是o(mlogn),但是常數巨大,所以能不findset就不要findset!!!

#include#include#include#include#include#define n 150003

using namespace std;

int n,m,top,st[n],father[n],rev[n],a[n];

int belong[n],fa[n],ch[n][2],val[n],mx[n];

int read()

int findset(int x)

int find(int x)

int isroot(int x)

int get(int x)

void update(int x)

void pushdown(int x)

}void rotate(int x)

void splay(int x)

}void access(int x)

}void rever(int x)

void link(int x,int y)

void merge(int x,int y)

int main()

for (int i=1;i<=m;i++)

else

} if (opt==2)

if (opt==3)

rever(x); access(y); splay(y); printf("%d\n",mx[y]);

} }}

BZOJ2959 長跑(lct 並查集)

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

bzoj2959 長跑 LCT 並查集

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

BZOJ 2959 長跑 LCT 並查集

真是被這題搞得心態大崩 調了7個小時 然而並查集都能寫成 o n 2 的我還能怪誰呢 顯然要把每個邊雙連通分量縮成點,點權為邊雙連通分量內所有點點權和,然後答案就等於兩點路徑上點權和 現在需要用lct維護,就比較麻煩 大概是一邊lct一邊使用並查集分別維護連通塊和邊雙連通分量 加邊時,若兩點不聯通,...