題目描述
某校開展了同學們喜聞樂見的陽光長跑活動。為了能「為祖國健康工作五十年」,同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加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 150010using 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的整數表示,每個地點設有若干個刷卡機。有...