laekov

BZOJ3237 [Ahoi2013]连通图

CDQ重构图。听上去比CDQ还高档的样子。


就是每层重新标号,把没有询问到的边拿来跑并查集。


最初是分开考虑然后可修复的并查集就T傻了。


#include <cstdio>

#include <cstring>

#include <cctype>

#include <set>

#include <algorithm>


using namespace std;


int _d_;

#define readInt(_x_) { \

int& _s_ = _x_; \

while (!isdigit(_d_ = getchar())); \

_s_ = 0; \

while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar())); \

}


const int maxn = 100009;

const int maxm = 200009;

const int maxl = 19;


struct edge {

int a, b, i;

};

struct dset {

int r[maxn], hp[maxn * 5], hv[maxn * 5], cnt;

void init(int n) {

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

r[i] = i;

cnt = 0;

}

int getRoot(int x) {

int p = x, q;

for (; r[p] ^ p; p = r[p]);

for (; x ^ p; x = q) {

/*hp[cnt] = x;

hv[cnt] = r[x];

++ cnt;*/

q = r[x];

r[x] = p;

}

return p;

}

bool connected(int x, int y) {

return getRoot(x) == getRoot(y);

}

bool merge(int x, int y) {

int a = getRoot(x), b = getRoot(y);

if (a ^ b) {

/*hp[cnt] = a;

hv[cnt] = a;

++ cnt;*/

r[a] = b;

return 1;

}

else

return 0;

}

void recover(int y) {

while (cnt > y) {

-- cnt;

r[hp[cnt]] = hv[cnt];

}

}

};

struct query {

int t, a[5];

void read() {

readInt(t);

for (int i = 0; i < t; ++ i)

readInt(a[i]);

}

};

struct parr {

int t, v[maxn];

void init() {

memset(v, 0, sizeof(v));

t = 0;

}

inline void next() {

++ t;

}

inline void ins(const int& x) {

v[x] = t;

}

inline bool query(const int& x) {

return v[x] == t;

}

};


int n, m, tq, ans[maxn], nn[maxn];

edge e[maxl][maxm];

dset s[maxl];

parr vis;

query q[maxn];


void cdq(int l, int r, int c, int d, int n, int m) {

if (c == 1) {

for (int i = l; i < r; ++ i)

ans[i] = 1;

return;

}

s[d]. init(n);

int mid = (l + r) >> 1;

vis. next();

for (int i = l; i < r; ++ i)

for (int j = 0; j < q[i]. t; ++ j)

vis. ins(q[i]. a[j]);

int cc = c, tn = 0, te = 0;

for (int i = 0; i < m; ++ i)

if (!vis. query(e[d][i]. i))

cc -= s[d]. merge(e[d][i]. a, e[d][i]. b);

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

if (s[d]. getRoot(i) == i)

nn[i] = ++ tn;

for (int i = 0; i < m; ++ i)

if (!s[d]. connected(e[d][i]. a, e[d][i]. b)) {

e[d + 1][te]. a = nn[s[d]. getRoot(e[d][i]. a)];

e[d + 1][te]. b = nn[s[d]. getRoot(e[d][i]. b)];

e[d + 1][te]. i = e[d][i]. i;

++ te;

}

if (l + 1 == r) {

ans[l] = (cc == 1);

}

else {

cdq(l, mid, cc, d + 1, tn, te);

cdq(mid, r, cc, d + 1, tn, te);

}

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


readInt(n);

readInt(m);

for (int i = 0; i < m; ++ i) {

readInt(e[0][i]. a);

readInt(e[0][i]. b);

e[0][i]. i = i + 1;

}

readInt(tq);

for (int i = 0; i < tq; ++ i)

q[i]. read();

vis. init();

cdq(0, tq, n, 0, n, m);

for (int i = 0; i < tq; ++ i)

puts(ans[i] ? "Connected" : "Disconnected");

}


评论

© laekov | Powered by LOFTER