BZOJ2959 長跑(lct 並查集)

2021-07-25 06:59:44 字數 1881 閱讀 9629

傳送門

用lct維護一顆動態樹。

如果連了某一條邊形成了乙個環,證明一次長跑這個環上的所有的點都可以被統計,所以可以將這個環縮成乙個點。用ufs來實現。

那麼一次長跑實際上就是在一條樹鏈上跑,只有乙個方向,在lct上維護乙個sum就可以了。

時間複雜度是均攤的,因為每乙個點至多被縮點一次,所以o(

k(ml

ogn+

n)α(

n)) 。lct常數非常大。

在卡常數的時候,由於每一次splay之前是要將所有的店pushdown的,所以只需要在pushdown的過程中find就可以了,這樣find少一點常數會小一點。

#include

#include

#include

using

namespace

std;

#define n 300005

#define inf 2100000000

int n,m,opt,a,b;

int f[n],ch[n][2],w[n],key[n],sum[n],rev[n],stack[n],q[n];

int dig[20];

int read()

while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();

return x*f;

}namespace check

int find(int x)

void merge(int x,int y)

}namespace ufs

int find(int x)

void merge(int x,int y)

}inline

int get(int x)

inline

bool isroot(int x)

inline

void update(int x)

inline

void pushdown(int x)

}}inline

void rotate(int x)

inline

void splay(int x)

for (int i=top;i;--i) pushdown(stack[i]);

for (int fa;!isroot(x);rotate(x))

if (!isroot(fa=f[x]))

rotate( (get(fa)==get(x))?fa:x );

}inline

void access(int x)

}inline

void reverse(int x)

inline

int find(int x)

inline

void un(int x,int y)

key[y]=sum[y]=cnt;

f[y]=0;

}inline

void link(int x,int y)

inline

void change(int x,int y,int v)

inline

int query(int x,int y)

inline

void write(int x)

dig[0]=0;

while (x)

for (int i=dig[0];i>=1;--i) putchar(dig[i]+'0');

putchar('\n');

}int main()

case

2:

case

3:

break;}}

}}

bzoj 2959 長跑(LCT 並查集)

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

bzoj2959 長跑 LCT 並查集

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

BZOJ 2959 長跑 LCT 並查集

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