清華集訓2015 靜態仙人掌 仙人掌剖分

2022-09-10 00:09:29 字數 4472 閱讀 1490

毒瘤仙人掌,明明放到樹上一道板題的非要構造到仙人掌上來出題orz orz orz orz orz

在oi的上古時代,流傳著這樣乙個故事:

有一天,小w到森林裡遊玩,回來之後跟小v說,我發現好多棵會動的樹耶!小v說,這有什麼好稀奇的,我用手指頭就能維護每棵樹的形態。

於是又過了幾天小w到沙漠裡遊玩,回來之後跟小v說,我發現好多棵會動的仙人掌耶!小v說,這有什麼好稀奇的,我用腳丫子就能維護每棵仙人掌的形態。

小s看到了這段故事,深受感動。他決定一步步做起,從仙人掌做起,從不會動的仙人掌做起。

本題中,我們定義:

如果乙個無向連通圖的任意一條邊最多屬於乙個簡單環,且不存在自環,我們就稱之為仙人掌。

仙人掌上的兩點間最短路徑(一定是簡單路徑)與最長簡單路徑的定義與一般無向圖的定義相同。

本題中,我們還保證任何乙個簡單環的長度均為奇數。這意味著不存在重邊,並且任意兩點間的最短路徑與最長簡單路徑一定是唯一的。

為了證明你確實能夠維護仙人掌,我們給你 $n$ 個結點,從 $1$ 到 $n$ 標號,其中 $1$ 號點是仙人掌的根。它有 $m$ 條邊,第 $i$ 條邊連線了結點 $u_i$ 與 $v_i$。

每個結點有乙個顏色(黑或白),初始時均為黑色。現在有 $q$ 次操作,每次操作格式為 $op$ $x$($1 \leq op \leq 3, 1 \leq x \leq n$):第一行三個用空格隔開的正整數 $n,m,q$ 表示一共有 $n$ 個結點,$m$ 條邊,$q$ 個操作。

接下來 $m$ 行,每行兩個空格隔開的正整數 $u_i, v_i$,表示一條邊。

接下來 $q$ 行,每行表示乙個操作,格式如上述。對於每個 $op=3$ 的操作,輸出一行相應的結果。input

7 9 11

1 21 3

2 33 4

3 54 5

5 65 7

6 73 1

3 23 3

1 73 1

3 23 3

2 73 1

3 23 3

output
715

3124

03

本題使用**測試。每個子任務有若干個測試點,分為 $8$ 個子任務,你只有通過乙個子任務的所有測試點才能得到這個子任務的分數。

前七個子任務的限制時間限制:$1\texttt$。空間限制:$768\texttt$。

$n, q \leq 50000$。

子任務1(7分)

$n \leq 2, q \leq 2000$。

子任務2(14分)

$n \leq 20, q \leq 2000$。

子任務3(9分)

$n, q \leq 2000$。

子任務4(17分)

保證 $m=n-1$,並且 $u_i=i,v_i=i+1$,且不存在 $op=2$ 的操作。

子任務5(14分)

保證 $m=n-1$,並且 $u_i < v_i$,且不存在 $op=2$ 的操作。

子任務6(11分)

保證不存在 $op=2$ 的操作。

子任務7(18分)

沒有特殊的限制與約定。

子任務8(10分)

空間限制縮小為 $128\texttt$。

我們發現,如果這只是一棵樹,嘿嘿嘿,那不就是裸的樹剖嗎。

可惜他是乙個仙人掌。

那麼我們就利用圓方樹來進行仙人掌剖分。對於仙人掌的剖分不能按照樹一樣直接剖,考慮到我們可能應該在同乙個環上的點剖在一起。那麼就這樣處理-->我們把所有的點分成三類點:0,在鏈上的點(除了1號點外不包括鏈根)1.在環上並且處於從重兒子到環根最短路徑上 2,在環上並且處於從重兒子到環根的長路徑上。

我們在樹剖的時候,如果遇到圓點繼續剖下去,遇到方點,將環按照環序加入到樹剖序中(在這裡我們都不考慮作為方點父親的那乙個圓點),並且跳過重兒子,之後再進行剖,並且給環上所有點記錄下型別,然後繼續剖。圓點樹剖記得子樹(仙人掌)範圍,方點記錄輕環兒子的範圍。

線段樹維護3種點黑點的和個數,帶lazy下放。

查詢就直接查詢那個點和那個點的子仙人掌。

修改的時候跳一跳,發現top是方點(說明是從方點的重兒子跳過來的),直接修改。如果top是圓點(說明到達top的父親方點的環的輕兒子),稍微特殊處理一下就好了。

code:

#include#include#include#include#includeusing namespace std;

const int maxn = 2e5+5;

/*0 the point on the line

1 the sort point on the cir

2 the long point on the cir

*/struct edge

}v,g;

int n,m,q,scc;

struct dddpos[maxn];

int kind[maxn];

namespace tajanwhile(o!=y);

g.adg(x,scc);

}} else low[x] = min(low[x],dfn[y]);}}

}int top[maxn],siz[maxn],dis[maxn],zerz[maxn],id[maxn],dy[maxn],tot,fa[maxn];

void dfsgsz(int x,int ba)

}void dfsgps(int x,int ace)

} else

dis[x]++; kind[x] = 0;

int pp = (dis[zerz[x]] <= (dis[x]>>1) )?1:2;

for(int it=g.la[x];it;it=g.nt[it])

}pos[x].r = tot;

++tot; id[zerz[x]] = tot; kind[zerz[x]] = 0; dy[tot] = zerz[x];

}dfsgps(zerz[x],ace);

for(int it=g.la[x];it;it=g.nt[it])

if(x<=n) pos[x].r = tot;

}namespace segz[maxn],*rt; int tot;

void chan(node *&p,int c)

void ptd(node *&p) }}

void upd(node *&p)

}void maketree(node *&p,int l,int r)

return;

}int mid = (l+r)>>1;

maketree(p->ls,l,mid); maketree(p->rs,mid+1,r);

upd(p);

for(int i=0;i<=2;i++) p->pt[i] = p->ls->pt[i] + p->rs->pt[i];

}void changeall(node *&p,int l,int r,int x,int y)

ptd(p);

int mid = (l+r)>>1;

if(y<=mid) changeall(p->ls,l,mid,x,y);

else if(x>mid) changeall(p->rs,mid+1,r,x,y);

else changeall(p->ls,l,mid,x,y),changeall(p->rs,mid+1,r,x,y);

upd(p);

}void changekind(node *&p,int l,int r,int x,int y,int cc)

ptd(p);

int mid = (l+r)>>1;

if(y<=mid) changekind(p->ls,l,mid,x,y,cc);

else if(x>mid) changekind(p->rs,mid+1,r,x,y,cc);

else changekind(p->ls,l,mid,x,y,cc),changekind(p->rs,mid+1,r,x,y,cc);

upd(p);

}int getsumall(node *&p,int l,int r,int x,int y)

}void solve(int x,int op) else else }}

seg::changekind(seg::rt,1,scc,id[1],id[x],op);

}int getans(int x)

int main()

tajan::tarjan(1);

dfsgsz(1,0);

top[1] = id[1] = dy[1] = tot = 1;

dfsgps(1,1);

seg::maketree(seg::rt,1,tot);

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

}

靜態仙人掌 模板 tarjan LCA

description 這是一道靜態仙人掌 block forest data structure 的模板題。如果您不知道什麼是仙人掌,那麼此處給出無向仙人掌圖的定義 任意一條邊至多只出現在一條簡單迴路的無向連通圖稱為仙人掌。給你乙個有 n 個點和 m 條邊的仙人掌圖,和 q 組詢問 每次詢問兩個點...

動態仙人掌(dinosaur

分析 這道題在考場看到我是完全的蒙蔽的,驚人的妄想著能否用資料離散化後的dp來騙分。我果然很菜。好吧,對於我這種菜雞來說,正解似乎有些難想,讓我們考慮從最基本的情況開始考慮。先將所有仙人掌按p為第一關鍵字排序,從左向右掃。這裡我們考慮乙個貪心策略,如果仙人掌兩兩之間距離足夠遠,則仙人掌之間跳躍的最小...

題解 仙人掌計數

題目傳送門 給出 q 個查詢,每次查詢 n 個點的無根有標號仙人掌有多少個。q le 5 times 10 4,n 131072 因為這道題太難碼了,所以先把題解寫了再寫 好奇怪啊 終於碼出來了,果然還是 text 好用 霧 為了方便,我們下面的答案其實求的是有根有標號的答案,最後除以 n 就好了。...