APIO2020 交換城市

2022-04-29 05:48:07 字數 2810 閱讀 5383

我是真的不穩定的垃圾選手。

對於一張圖來說,兩個人能滿足題面關係等價於這張圖不是鏈,很好證明,如果有度數 \(> 2\) 的點,讓乙個人跑到乙個度數 \(= 1\) 的地方就可以了。

如果離線就可以什麼啟發式合併 + 並查集做到乙個 \(\log\)。就是合併兩個點 \(x, y\),動態維護每個聯通塊是不是鏈。

#include #include #include using namespace std;

const int maxn = 100005, maxm = 200005;

int n, m, arr[maxm], tot;

struct e

} e[maxm];

struct t;

struct array

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

build(t[p].l, l, mid, o);

build(t[p].r, mid + 1, r, o);

} void update(int &p, int q, int l, int r, int x, int o)

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

if (x <= mid) update(t[p].l, t[q].l, l, mid, x, o);

else update(t[p].r, t[q].r, mid + 1, r, x, o);

} int query(int p, int l, int r, int x)

void inline set(int x, int k, int i)

int inline get(int x, int i)

} p, f, d, sz;

int find(int x, int i)

void inline merge(int x, int y, int i) else

}void init(int n, int m,

std::vectoru, std::vectorv, std::vectorw) ;

} sort(arr + 1, arr + 1 + tot);

tot = unique(arr + 1, arr + 1 + tot) - arr - 1;

sort(e, e + m);

f.build(f.rt[0], 0, n - 1, -1), sz.build(sz.rt[0], 0, n - 1, 1);

p.build(p.rt[0], 0, n - 1, 0), d.build(d.rt[0], 0, n - 1, 1);

for (int i = 1, j = 0; i <= tot; i++) }}

bool inline check(int x, int y, int i)

int getminimumfuelcapacity(int x, int y)

return arr[r];

}

然後就去無恥的看題解,然後去學了一下 kruscal 重構樹。

我們不妨設計乙個特殊的 kruscal 重構樹,使得對於 \(x, y\) 的詢問,答案就是他們的 lca ,即他們的 lca 是合併過程中讓他們從鏈變成不是鏈的那條關鍵邊!

那麼,設計一種類似於普通 kruscal 最小重構樹的方式,只不過改動如下:

發現這麼構造仍然滿足大根堆性質。

用啟發式合併儲存當前聯通塊的所有點,每個原始點只會連一次,即連向他所在聯通塊轉變的關鍵邊新點,所以複雜度是 \(o(n \log n)\) 的。

正確性:在 lca 這個子樹中,所有邊都是 \(\le w_\) 的,lca 的子樹形成的結構不是鏈,因為只有不是鏈才會連邊,所以必然 lca 的權值是可以的。然後證明 \(ans \ge w_\)。\(ans < w_\) 顯然是不行的,因為他們要用這條關鍵邊。所以 \(ans = w_\)。

所以每次詢問求個 lca 就行了。

時間複雜度 \(o((n + q) \log n)\)

我**偷了一下懶,即只在鏈的時候維護各種資訊,已經不是鏈了,除了 \(f\) 陣列剩下就不用維護。

#include "swap.h"

#include #include #include using namespace std;

const int n = 100005, m = 200005, l = 19;

int n, m, f[n << 1], fa[n << 1][l], dep[n << 1], cnt, sz[n], a[n << 1];

bool ch[n << 1], d[n];

vectorg[n << 1];

vectorc[n << 1];

struct e

} e[m];

int find(int x)

void dfs(int u)

}int lca(int x, int y)

void inline merge(int u, int v, int w)

} else else

}}void init(int n, int m, std::vectoru, std::vectorv, std::vectorw) ;

sort(e + 1, e + 1 + m);

for (int i = 1; i < 2 * n; i++)

for (int i = 1; i <= m; i++) merge(e[i].u, e[i].v, e[i].w);

if (cnt > n)

dfs(cnt);

}int getminimumfuelcapacity(int x, int y)

APIO2020 粉刷牆壁

考場想了 5.5 h,第一部分分死活打不出來,做到崩盤,現在重做,感覺自己就是乙個sb,放學在地鐵上一眼就會了。哎。可以把乙個要求看作乙個長度為 m 的區間 l,l m 1 可以要求這段條件的充要條件是找到一種迴圈移位,每個牆恰好可以被那個工人挖。然後問題是用最少的區間覆蓋完 0,n 1 可以設乙個...

網易2020筆試真題 序列交換

題目描述 小易給你乙個包含n個數字的陣列a1,a2,an。你可以對這個陣列執行任意以下交換操作 對於陣列中的兩個下標i,j 1 i,j n 如果ai aj為奇數,就可以交換ai和aj 現在允許你使用操作次數不限,小易希望你能求出在所有通過若干次操作可以得到的陣列中,字典序最小的乙個是什麼 輸入描述 ...

布局智慧型城市建設,2020高交會雲天勵飛創新謀變

今日,第二十二屆高交會順利在深圳拉開帷幕,高交會被譽為 中國科技第一展 也是科技創新成果集中展示的最大平台。在本屆高交會上,雲天勵飛展出了 新基建 雲天勵飛城市智慧型體 ai疫情態勢感知系統 ai書城智慧型屏 等產品和解決方案,吸引了眾多參觀者駐足 最受關注 ai疫情防控平台 今年,新冠疫情肆虐全球...