CDQ分治 帶權並查集 JZOJ 4769

2022-04-30 19:51:07 字數 1595 閱讀 9424

description

對於乙個圖, 如果它的點集能被分成兩個部分, 使得在原圖中每一部分之間的點沒有任何邊相連,則該圖被稱為二分圖。

現在給定乙個無向圖,每次增加一條邊,或者刪除一條邊。要求您每次判斷它是不是二分圖。

input

第一行兩個數n,m,表示該圖的點數和運算元。

接下來m行,以乙個數type開頭。type為0或1。若type為1則表示加一條邊,接下來輸入兩個數a,b表示它連線的邊的編號,編號從0到n-1;為0則表示刪除一條邊,接下來是乙個數a表示刪除加入的第a+1條邊。

保證任何時候圖都無重邊或自環。

output

m行,每行乙個"yes"或"no"(引號不輸出),表示每次操作後圖是否是二分圖。

sample input

3 3

1 0 1

1 0 2

1 1 2

sample output

yes

yesno

data constraint

我們發現其實只是圖上的邊會在[l,r]的時間內存在罷了

那麼我們可以來一波cdq

用乙個vector存邊,然後如果跨越當前區間的邊就拆到左邊或右邊的邊集l,r中

同時要存一下並查集的狀態,不能路徑壓縮否則無法還原,用按秩合併和棧記錄並查集存邊順序,跳出當前層分治時還原並查集

#pragma gcc optimize(2)#include 

#include

#include

using

namespace

std;

const

int n=3e5+10

;struct

edge ;

vector

g;int

f[n],r[n],stk[n],d[n];

intn,m,top;

bool

ans[n];

int find(int x)

int dist(int x)

void merge(int i,int j,int

dist)

void pop(int

now)

}void divide(int l,int r,vectorg)

}else

if (i->r<=mid) ll.push_back(*i);

else

if (i->l>mid) rr.push_back(*i);

else

); rr.push_back((edge));

}if (l!=r) divide(l,mid,ll),divide(mid+1

,r,rr);

pop(now);

}int

main() );

}else

}for (int i=0;ii;

divide(

1,m,g);

for (int i=1;i<=m;i++) printf(ans[i]?"

no\n

":"yes\n");

}

view code

並查集,帶權並查集

題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...

帶權並查集

食物鏈 time limit 1000ms memory limit 10000k total submissions 71395 accepted 21146 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...

帶權並查集 then

問題 b 便 時間限制 2 sec 記憶體限制 512 mb 提交 50 解決 14 題目描述 給出乙個r c的棋盤.共有r行c列,r c個格仔.現要在每個格仔都填乙個非負整數.使得任意乙個2 2的正方形區域都滿足這樣的性質 左上角的數字 右下角的數字 左下角的數字 右上角的數字.有些格仔已經確定,...