bzoj4537 HNOI2016 最小公倍數

2021-07-13 09:06:21 字數 1749 閱讀 7395

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個詢問,每次詢問給定四個引數u、v、a和b,請你求出是否存在一條頂點u到v之間的路徑,使得

路徑依次經過的邊上的權值的最小公倍數為2^a*3^b。注意:路徑可以不是簡單路徑。下面是一些可能有用的定義

:最小公倍數:k個數a1,a2,…,ak的最小公倍數是能被每個ai整除的最小正整數。路徑:路徑p:p1,p2,…,pk是頂

點序列,滿足對於任意1<=ii和pi+1之間都有邊相連。簡單路徑:如果路徑p:p1,p2,…,pk中,對於任意1

<=s≠t<=k都有ps≠pt,那麼稱路徑為簡單路徑。

輸入檔案的第一行包含兩個整數n和m,分別代表圖的頂點數和邊數。接下來m行,每行包含四個整數u、v、a、

b代表一條頂點u和v之間、權值為2^a*3^b的邊。接下來一行包含乙個整數q,代表詢問數。接下來q行,每行包含四

個整數u、v、a和b,代表一次詢問。詢問內容請參見問題描述。1<=n,q<=50000、1<=m<=100000、0<=a,b<=10^9

對於每次詢問,如果存在滿足條件的路徑,則輸出一行yes,否則輸出一行 no(注意:第乙個字母大寫,其餘

字母小寫) 。

4 5

1 2 1 3

1 3 1 2

1 4 2 1

2 4 3 2

3 4 2 2

5 1 4 3 3

4 2 2 3

1 3 2 2

2 3 2 2

1 3 4 4

yes

yes

yes

no no 分塊

好題問題轉化為:每個邊有兩個權值a和b,每次詢問兩點之間是否存在一條路徑滿足路徑上a的最大值和b的最大值分別等於乙個數。

把邊按照a排序,然後分塊。

每次處理a的範圍在當前塊內的詢問。假設處理到第i塊,把詢問和前i-1塊按照b排序,這些部分o(n)就可以處理了。第i塊裡的邊暴力處理,然後撤銷修改。然後用乙個並查集維護集合最大值。

#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define n 200005

#define inf 1000000000

using namespace std;

int n,m,q,block,cnt,tot,f[n],sz[n],mxa[n],mxb[n];

bool ans[n];

struct dataa[n],b[n],c[n];

struct optop[n];

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline bool cmpa(const data &a,const data &b){return a.a==b.a?a.b=a[i].a&&(i+block>m||b[j].a

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。注意 路徑可以不是簡單路徑。下...

bzoj4537 Hnoi2016 最小公倍數

傳送門 思路 把邊按a排序,每sqrt m 分一組 然後把詢問按b排序,把在這組及以前的邊按b排序 把這些邊用並查集一條一條插入並維護 零散的部分暴力插入並記錄,做完後暴力撤銷 注意 並查集不能路徑壓縮,否則無法撤銷回去 include include include include include...