題目鏈結
題意:一張 $ n $ 點 $ m $ 邊無向圖,每條邊有編號。若乙個區間內的邊能連成乙個環,則稱這個區間為好區間。求每條邊分別在多少個好區間內。
演算法一:
首先想到乙個暴力。列舉區間的左端點,右端點,用並查集判斷是否有環,得分 $ 60 $ 分。
演算法二:
顯然的優化1:設 $ [l, r] $ 表示從 $ l $ 到 $ r $ 的區間滿足條件且從 $ l $ 到 $ r - 1 $ 的區間不滿足條件。 $ l $ 遞增,顯然 $ r $ 不降。
顯然的優化2:對於統計答案,記錄首項和公差,最後跑一邊字首和。
對於優化1,我們需要乙個可以支援加邊和刪邊的並查集, $ lct $ 即可。
得分 $ 90 $ ~ $ 100 $ 分( $ findroot $ 時將結果 $ splay $ 試試?)。
#include#define lc ch[u][0]
#define rc ch[u][1]
using namespace std;
const int n=400010;
typedef long long ll;
int m,a[n],b[n];
int fa[n],ch[n][2],sta[n];
bool lz[n],flag;
ll ans[n],dl[n];
inline bool nroot(int u)
void pushdown(int u)
inline void pushup(int u)
void rotate(int u)
void splay(int u)
}void access(int u)
void makeroot(int u)
int findroot(int u)
void split(int x,int y)
void lnk(int x,int y)
void cut(int x,int y)
int main()
lnk(a[r],b[r]);
} if(!flag) break;
ans[l]=m-r+1,--dl[r+1],--r,cut(a[l],b[l]);
} ll sum=0;
for(int i=1;i<=m;i++) sum+=dl[i],ans[i]=ans[i-1]+ans[i]+sum;
for(int i=1;i<=m;i++) printf("%lld ",ans[i]);
return 0;
}
題解 洛谷 P4230 連環病原體
用雙指標掃瞄來找環,加入 r 位置的邊後,若形成了環,就刪去 l 位置的邊,直到環斷掉,加邊刪邊和判定連通性用 lct 維護即可。考慮如何計算環的貢獻,對於區間 l,r 若其形成了環,則區間 l,r 1 l,r 2 dots l,m 都形成了環。得最終的貢獻為區間 l,r 都加上 m r 1 區間 ...
Luogu4230 連體病原體
題面戳我 很好想 很好寫的一道題,然而比賽中我還是沒有切掉qaq。lct列舉左端點 i 向右移動右端點指標 j 找到第乙個成環的位置。此時 i,j i,j 1 i,m 都是合法答案。可見就是在區間 i,j 上區間加 m j 1 再在 j 1,m 上加上乙個等差數列 m j,m j 1.1 等差數列直...
資料結構與演算法實驗題7 2 連環計
問題描述 赤壁之戰前夕,龐統向周瑜獻連環計,瑜設計使蔣幹邀龐統到曹營。操與統同觀營寨,又共論兵法。統對答如流使操敬服。統乘機提出 大江中風浪不息使北兵易生疾病。可將大 小船配搭,首尾用鐵環連鎖,鋪闊板以便人馬行走。操聞之大喜,派人連夜打造連環大釘,鎖住船隻。每打造一單位長度的鐵索要花費一單位的錢,曹...