HNOI2016 最小公倍數

2021-07-26 19:40:53 字數 2007 閱讀 8500

這是hnoi2016的day1t1;

是一道眾多cj神犇口中的水題,也是ymd 用分塊,莫隊打天下的第一站;

這個題只要數學沒有跪爛,應該還是可以看出來,

目標是要判定是否存在路徑使x,y聯通,且路上的a的最大值等於a,b的最大值等於b;

好我們先考慮暴力怎麼解決;

對於前二十分,我們考慮對於每組詢問,只加入a<=a且b<=b的邊,在用並查集判斷是否聯通以及最大值是否為a和b;

好的,那麼我們該怎麼做呢;

首先我們身在hn,那麼我們的腦海中一定要裝著兩個演算法:莫隊和cdq,這是hn的驕傲!!

其次我們要謹記網管的教導「暴力出奇蹟」,

「這題你不會,那你打個暴力就可以了嘛,暴力就可以ac嘛」;

謹記王隊長的傳奇「暴力進省隊」;

所以這題的正解就是比純暴力好一點點大暴力:分塊!!!

思想和暴力及其類似:我們把邊按照a sort,再進行分塊,再把詢問按照 b 進行排序;

1.我們對於每個塊,先把前i-1個塊中的邊全部搞出來,再把對於滿足這個塊的a(即大於等於這個塊的開頭,小於等於這個塊的結尾)的詢問全部全部搞出來。並把搞出來的邊按照b進行排序。

2.然後再列舉這些滿足a的詢問,有兩步操作,乙個是算這個塊之前的貢獻,乙個是算這個塊對當前詢問的貢獻;

3.第一步,因為前面已經按a排序了,所以前面的這些邊的a值是一定滿足詢問的a的限制的,所以我們只要把已經按照b排了序的邊判斷是否滿足詢問的b的條件再依次加入

4.第二步,因為a和b都不一定滿足要求,所以我們需要暴力對這個塊中的邊進行兩次判斷,即a和b都需要判斷,再加入這條邊;

5.並且由於滿足這個塊的詢問的a並不一定是公升序的,所以可能對於滿足的兩個詢問i,j;

biaj;這樣就會有乙個尷尬的問題,一條邊的ax可能滿足aj

6.這樣這個題目就可以ac了;

7.最後記得常數優化,cmp要打 const &,不然會gi爛;

// made by qt666

#include#include#include#include#include#include#include#define rg register

using namespace std;

const int n=100050;

int gi()

int n,m,fa[n],maxa[n],maxb[n],size[n],tot2,tot,ans[n];

int find(rg int x)

struct ac

e[n],query[n],old[n];

struct ac

add[n];

bool cmpa(const ac &a,const ac &b)

; if(x==y)

fa[x]=y;size[y]+=size[x];

maxa[y]=max(maxa[x],max(maxa[y],a));

maxb[y]=max(maxb[x],max(maxb[y],b));

}void del()

tot2=0;

}int main()

{ n=gi(),m=gi();

rg int block=(int)sqrt(m);

for(rg int i=1;i<=m;i++) e[i].x=gi(),e[i].y=gi(),e[i].a=gi(),e[i].b=gi(),e[i].id=i;

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

rg int t=gi();

for(rg int i=1;i<=t;i++) query[i].x=gi(),query[i].y=gi(),query[i].a=gi(),query[i].b=gi(),query[i].id=i;

sort(query+1,query+1+t,cmpb);

for(rg int i=1;i<=m;i+=block)

{tot=0;

for(rg int j=1;j<=t;j++)

{ if(query[j].a>=e[i].a&&(i+block>m||query[j].a

HNOI2016 最小公倍數

給定乙個 n 個點 m條邊的無向圖,每條邊有兩個引數 a b q 個詢問,每個詢問給s,t,a,b,求是否存在一條 s 到 t的路徑 是 路徑 而不是 簡單路徑 使得經過的邊中am ax a bma x b n,q 50000 m 105 a,b 109 暴力的想法就是對於每個詢問,只加a qa且b...

HNOI2016 最小公倍數

題目 不難發現題意就是,每條邊有兩種權值,每次詢問兩個點 u,v 問 u 到 v 是否存在一條路徑滿足第一類邊權的最大值為 a 第二類邊權的最大值為 b 乙個直觀的暴力做法就是把 a i leq a,b i leq b 的邊都加進來,看看加入這些邊後 u,v 是否聯通 如果聯通,在看看 u,v 所在...

HNOI2016 最小公倍數

分塊,並查集 對邊 a 和詢問 b 分別排序 邊分塊處理,找出當前塊內所有的詢問一起處理 對於每乙個塊的詢問 對於前面塊內的邊,a肯定比當前詢問小,所以按b排序,一條條加入並查集,直到超過詢問的b 這一步可以雙指標維護,就不用標記了 暴力遍歷該塊,找到符合要求的邊,加入並查集,同時標記 並查集判聯通...