洛谷
因為拼湊起來的部分分比較多,所以就放一起了。
以下設詢問的\(a,b\)為\(a,b\),
複雜度\(o(nm)\)的:將所有\(a\leq a,b\leq b\)的邊兩端,用並查集並起來,再看一看等於\(a,b\)的是否有端點在集合中即可。
一條鏈的:拿線段樹之類的資料結構維護一下即可。
\(a\)等於\(0\)的:將邊的和詢問按照\(b\)排序,用\(two\;pointers\)掃一遍丟到並查集中即可。
首先考慮暴力,每次詢問暴力求出所有\(\leq a, \leq b\)的邊,然後判斷判斷兩點是否聯通,並且聯通塊內最大值是否合法就可以了。
接下來的\(a\)和\(b\)還是是詢問的\(a, b\)。
將所有的邊按照\(a\)排序並分塊,將所有的詢問按照\(b\)排序。
設第\(i\)塊的區間是\([l_i, r_i]\),找出所有的\(a \in [a_, a_)\)的詢問,然後乙個乙個處理。
對於第\(j\)個詢問,有兩種邊可以產生貢獻,一種是在\([1, i)\)的\(b \leq b_j\)的邊,這種邊可以用乙個指標維護。
還有一種是在第\(i\)塊的\(a \leq a_j\),\(b \leq b_j\)的邊,這種邊最多只有塊的大小條,可以暴力加邊。
因為每一次加了第二種邊之後要撤銷這些操作,所以要寫乙個支援撤銷的並查集。
然後,當塊的大小為\(\sqrt\)時據說最快。
(感謝\(xgzc\)友情提供)
#include #include #include #include #include #include using namespace std;
inline int gi()
const int max_n = 2e5 + 5;
struct edge e[max_n];
struct query q[max_n], p[max_n];
struct node stk[max_n];
bool cmp1(const edge &l, const edge &r)
bool cmp2(const edge &l, const edge &r)
bool c***(const query &l, const query &r)
int n, m, q, top, ans[max_n], fa[max_n], a[max_n], b[max_n], size[max_n];
int getf(int x)
void merge(int x, int y, int a, int b) ;
if (x != y)
fa[x] = y, size[y] += size[x], a[y] = max(a[x], a[y]), b[y] = max(b[x], b[y]);
a[y] = max(a[y], a);
b[y] = max(b[y], b);
}int main() ;
q = gi();
for (int i = 1; i <= q; i++) q[i] = (query);
sort(&e[1], &e[m + 1], cmp1);
sort(&q[1], &q[q + 1], c***);
for (int i = 1, len = sqrt(m * log2(n)); i <= m; i += len)
} }
for (int i = 1; i <= q; i++) puts(ans[i] ? "yes" : "no");
return 0;
}
bzoj4537 HNOI2016 最小公倍數
time limit 40 sec memory limit 512 mb submit 563 solved 236 submit status discuss 給定一張n個頂點m條邊的無向圖 頂點編號為1,2,n 每條邊上帶有權值。所有權值都可以分解成2 a 3 b 的形式。現在有q個詢問,每次...
BZOJ4537 HNOI2016 最小公倍數
那個,事情是這樣的,從前有乙隻蒟蒻 對,就是我 然後有一天他心血來潮想創個部落格。可是沒過多久,他的熱情就過去了,甚至連一篇博文都沒有寫。然後,不知道怎麼了,他的部落格就被機房裡的dalao翻出來了,還被嘲諷了一番。於是他決定補救一下他的部落格。嗯,就這樣。這道題大概是這樣的。給定一張n個點m條邊的...
BZOJ4537 Hnoi2016 最小公倍數
給定一張n個頂點m條邊的無向圖 頂點編號為1,2,n 每條邊上帶有權值。所有權值都可以分解成2 a 3 b 的形式。現在有q個詢問,每次詢問給定四個引數u v a和b,請你求出是否存在一條頂點u到v之間的路徑,使得 路徑依次經過的邊上的權值的最小公倍數為2 a 3 b。注意 路徑可以不是簡單路徑。下...