@(サマースクールキャンプオフ以上2019頭の牛(セッション8)E_Explorer)
質問の意味:
タイトル同様:CF366D、Gym101652T
この質問(N(100000)\)\点\(M(10000)\)のエッジ、各無向エッジが番号可能[李は、R]((\ 1 \ルリチウム\ルRiを\)\)ル 1E9 の人々から尋ねた\(1 \は)します\(N \)どのように多くの人が合格します。
分析:
Lvは30無駄に複数のレースの暴力。。。
元のデータの範囲は、実際には、離散間隔列挙暴力の実行であると思われるタイトル1000年、前に行われるため、\(\ DFS)をクエリまたは暴力的な範囲で実行\(BFS \)再び最後のチェック。。。
鶏料理、主に限られた思考の涙を流し、これは非常に致命的です。
私はこの問題はLCTが取り消さや言葉遣いセット+セグメントツリーをチェックします今書くことができると聞きました。。
- 上記のすべての重み離散瞬間、また非常に明確で述べたように、その後、キーワードを構築し、ツリーラインの右側にあります
- つまり、各リーフノードは、いくつかの重量範囲を表し、のも、このセグメントの木とEのオフ正確に同じ質問の牛は、左のことを言及してみましょうとツリーラインを開閉する権利。ツリーラインのこの解釈:ここの壁紙
- 次に、現在の重量範囲点の全ての側面をカバーするために格納されたツリーセグメントの各ノード。
- 更新間隔が終了した後、全体の歯ツリーウォーキングは再び答えます。
- エッジを互いに素なセットの接続性を維持するとともに、この重み間隔のルートにリーフノードに含まれます。
- 上記の取消しのほとんど副作用をバックトラックするには。次いで合わせたルートの両側のレコードを、それらを復元する\(FA []、RNK [ ] \) ラインに。
- スタックエッジが追加されたレコードができるとともに、本構造のLIFO動作は、適切な失効問題です。また、取消互いに素-設定されたパスを圧縮することができない、それはランクによってマージする必要があります。
コード
const int MXN = 3e3 + 7;
const int MXE = 2e6 + 7;
int n, m;
vector<int> sum[MXN<<2], vs;
int fa[MXN], rnk[MXN], top;
struct lh {
int fi, se, u, v;
}stak[MXN];
struct lp {
int u, v, l ,r;
}cw[MXN];
void update(int L, int R, int v, int l ,int r, int rt) {
if(L <= l && r <= R) {
sum[rt].eb(v);
return;
}
int mid = (l + r) >> 1;
if(L > mid) update(L, R, v, mid + 1, r, rt<<1|1);
else if(R <= mid) update(L, R, v, l, mid, rt<<1);
else {
update(L, mid, v, l, mid, rt<<1), update(mid + 1, R, v, mid + 1, r, rt<<1|1);
}
}
int Fi(int x) {
return fa[x] == x? x: Fi(fa[x]);
}
int pa, pb, ans;
void build(int l, int r, int rt) {
if(l == r) {
// debug(l, r, Fi(3), Fi(5))
for(auto x: sum[rt]) {
pa = Fi(cw[x].u), pb = Fi(cw[x].v);
if(pa == pb) continue;
// debug(l, r, cw[x].u, cw[x].v)
if(rnk[pa] > rnk[pb]) swap(pa, pb);
fa[pa] = pb;
rnk[pb] += rnk[pa];
stak[++ top] = {rt, x, pa, pb};
}
if(Fi(1) == Fi(n)) ans += vs[l+1] - vs[l];
while(top && stak[top].fi == rt) {//撤销
int x = stak[top].se;
if(rnk[stak[top].u] > rnk[stak[top].v]) {
fa[stak[top].v] = stak[top].v;
rnk[stak[top].u] -= rnk[stak[top].v];
}else {
fa[stak[top].u] = stak[top].u;
rnk[stak[top].v] -= rnk[stak[top].u];
}
-- top;
}
// debug(l, r, Fi(3), Fi(5))
return;
}
int mid = (l + r) >> 1;
// debug(l, r, mid, rt)
for(auto x: sum[rt]) {
pa = Fi(cw[x].u), pb = Fi(cw[x].v);
if(pa == pb) continue;
// debug(pa, pb)
if(rnk[pa] > rnk[pb]) swap(pa, pb);
fa[pa] = pb;
rnk[pb] += rnk[pa];
stak[++ top] = {rt, x, pa, pb};
}
build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
while(top && stak[top].fi == rt) {//撤销
int x = stak[top].se;
if(rnk[stak[top].u] > rnk[stak[top].v]) {
fa[stak[top].v] = stak[top].v;
rnk[stak[top].u] -= rnk[stak[top].v];
}else {
fa[stak[top].u] = stak[top].u;
rnk[stak[top].v] -= rnk[stak[top].u];
}
-- top;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
// freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read();
for(int i = 1; i <= n; ++i) fa[i] = i, rnk[i] = 1;
vs.eb(0);
for(int i = 1; i <= m; ++i) {
cw[i].u =read(), cw[i].v = read();cw[i].l = read(), cw[i].r = read();
vs.eb(cw[i].l), vs.eb(cw[i].r + 1);
}
my_unique(vs);
// for(auto x: vs) printf("%d ", x); printf("\n");
for(int i = 1; i <= m; ++i) {
update(lower_bound(all(vs), cw[i].l) - vs.begin(), upper_bound(all(vs), cw[i].r) - vs.begin() - 1, i, 1, vs.size() - 1, 1);
// debug(lower_bound(all(vs), cw[i].l) - vs.begin(), upper_bound(all(vs), cw[i].r) - vs.begin() - 1, cw[i].u, cw[i].v);
}
build(1, vs.size() - 1, 1);
printf("%d\n", ans);
return 0;
}
:演習完了するために、2つのCF 813F取消互いに素セット+パーティション、互いに素セットの失効とCDQ +のBZOJ 3237パーティション
レビュー加重互いに素セットと永続互いに素セットを。