傳送門
用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一邊使用並查集分別維護連通塊和邊雙連通分量 加邊時,若兩點不聯通,...