dtoi4543 HNOI2016 最小公倍數

2022-07-10 04:42:13 字數 2705 閱讀 8628

題意:

給定一張 $ n $ 個頂點 $ m $ 條邊的無向圖(頂點編號為 $ 1,2, \cdots ,n $),每條邊上帶有權值。所有權值都可以分解成 $ 2^a \cdot 3^b $ 的形式。

現在有 $ q $ 個詢問,每次詢問給定四個引數 $ u $、$ v $、$ a $ 和 $ b $,請你求出是否存在一條頂點 $ u $ 到 $ v $ 之間的路徑,使得路徑依次經過的邊上的權值的最小公倍數為 $ 2^a \cdot 3^b $ 。

$1 \leq n,q \leq 50000,\ 1 \leq m \leq 100000,\ 0 \leq a,b \leq 10^9 $。

題解:

顯然,此題題意就是問存不存在一條路徑,使得兩種型別的最大值分別等於給定值。

假如只有一種型別的話,可以先從小到大排序,按數值大小順序加入操作和詢問,用並查集維護連通塊和最大值就行了。

如果有兩種型別,可以先按照一維從小到大排序,按順序加入操作和詢問,但是處理詢問的時候,顯然並不是所有的邊都能被用上,只有另一種型別同時也小於等於詢問的值才能用上,這有點像二維偏序,但是分治似乎沒有辦法解決這個問題。

換句話說,現在需要解決的問題就是動態維護權值前 $i$ 小的邊所形成的並查集(由於第一種權值排序了,所以只要管第二種權值),似乎非常困難。但是通過觀察時限和資料範圍可以猜測需要根號演算法。

先嘗試將 $m$ 個權值從小到大分成 $b$ 塊,每乙個塊維護乙個並查集,第$i$ 個並查集表示前 $i-1$ 塊中的邊所形成的並查集。那麼每次插入操作相當於把後面一段連續的塊的並查集都進行一次合併操作。查詢相當於拿著某一塊的並查集,把剩下的邊給暴力乙個乙個加入進去,再判斷。這樣只需要乙個可以支援後退操作的並查集就行了,效率為 $o(n*max(m/b,b)*\log_2n)$。然而我寫出來的**不知道為什麼塊開成 $\sqrt$ 過不了,開成 $\sqrt*log_2m$才能過,應該是因為查詢操作次數少吧。

#include#include

#include

#include

#include

using

namespace

std;

int n,m,q,f[320][50002],maxa[320][50002],maxb[320][50002

],fk,len;

short dep[320][50002

];bool fl[50002],ans[50002

];map

wz;typedef

struct

p;typedef

struct

pp;typedef

struct

ppp;

ppp t[

200002

];bool

cmp(p aa,p bb)

bool

cmpp(ppp aa,ppp bb)

p p[

200002

];pp dl[

10000

];int find(int x,int

y)void jl(int nw,int

x)void hb(int nw,int x,int y,int a,int b,bool

u)

if (fx==fy)

if (dep[fx]>dep[fy])swap(fx,fy);

dep[nw][fy]=max(dep[nw][fy],(short)(dep[nw][fx]+1

)); maxa[nw][fy]=max(maxa[nw][fy],max(maxa[nw][fx],a));

maxb[nw][fy]=max(maxb[nw][fy],max(maxb[nw][fx],b));

f[nw][fx]=fy;

}int

main()

scanf("%d

",&q);

for (int i=1;i<=q;i++)

sort(p+1,p+(m+q)+1,cmp);sort(t+1,t+m+1,cmpp);fk=sqrt(m*log2(m));

for (int i=1;i<=m;i++)if (!wz.count(t[i].b))wz[t[i].b]=i;

for (int i=1;(i-1)*fk+1

<=m;i++)

for (int j=1;j<=n;j++)

for (int i=1;i<=m+q;i++)

if (!p[i].num)

else

for (int j=(nw-1)*fk+1;j<=nw*fk&&j<=m;j++)

if (fl[j] && t[j].b<=p[i].b)hb(nw,t[j].u,t[j].v,t[j].a,t[j].b,1

);

int fx=find(nw,p[i].u);

if (fx==find(nw,p[i].v) && maxa[nw][fx]==p[i].a && maxb[nw][fx]==p[i].b)ans[p[i].num]=1

;

for (int j=len;j>=1;j--)

}for (int i=1;i<=q;i++)if (ans[i])puts("

yes");else puts("no"

);

return0;

}

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