無向グラフ、所与\(Q \)ユニコム図かどうか、元の画像のエッジを削除しようと、質問時間の後、各時間辺問い合わせの所定の数。
\(N、\ Q \ ^ leq10。5、\ M \ leq2 \ times10。5 ^ \) 、チャレンジ当たりの辺の数\(\ leq4 \)
CDQ分割統治、分割統治、互いに素なセット
実際には、これは厳密にCDQパーティションを捉えることができない......
一部と最適化の複雑さとのお問い合わせダブルカウントを最大化するために考慮されるべきです
、隔壁によって現在のインターバル時間質問を考える\([L、\ R&LT] \)互いに素なセットブロックとの通信を維持し、これらのエッジの問い合わせを除去した後に、
反対側の寄与再帰第一側を消去する前に、他方の側縁無添加互いに素なセットの側にので、重複排除は、空の配列を使用して実施することができます
そして\([L、\中間] 、\ [ミッド+ 1、\ R] \) 互いに素なセットの処理は、共有することができる\([L、\中間] \) バックした後に元に戻すことができ(\を[L、\ R] \)状態、再処理\([MID +。1、\のR&LT] \) 。各操作は一度だけ取り消されますので、時間の複雑さが保証されているので、
時間複雑\(O(\ displaystyle \和のq \ログ\和Q)\)
コード(C ++ 11を開きます)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
bool ans[maxn];
int n, m, q, k;
struct edge {
int u, v;
} e[maxn << 1];
vector <int> Q[maxn];
#define nc getchar()
inline int read() {
int x = 0;
char c = nc;
while (c < 48) c = nc;
while (c > 47) x = (x << 3) + (x << 1) + (c ^ 48), c = nc;
return x;
}
#undef nc
// ---
bool vis[maxn << 1];
int now, T[maxn << 1];
inline void clr() { ++now; }
inline void upd(int pos) {
T[pos] = now, vis[pos] = 1;
}
inline bool query(int pos) {
return T[pos] < now ? 0 : vis[pos];
}
// array with clear
int par[maxn], sz[maxn];
int tot, top, st[maxn], bl[maxn];
inline int find(int x) {
while (par[x] != x) x = par[x];
return x;
}
inline void unite(int x, int y) {
if ((x = find(x)) != (y = find(y))) {
if (sz[x] < sz[y]) swap(x, y);
--tot;
par[y] = x, sz[x] += sz[y];
st[++top] = y, bl[top] = k;
}
}
inline void revert() {
for (; bl[top] >= k; --top, ++tot) {
int u = st[top];
sz[par[u]] -= sz[u], par[u] = u;
}
}
// union set
void cdq(int l, int r) {
if (l == r) {
ans[l] = tot == 1; return;
}
int mid = (l + r) >> 1;
for (int i = l; i <= mid; ++i) {
for (int p : Q[i]) upd(p);
}
for (int i = mid + 1; i <= r; ++i) {
for (int p : Q[i]) {
if (!query(p)) unite(e[p].u, e[p].v);
}
}
clr();
k <<= 1, cdq(l, mid), k >>= 1;
revert();
for (int i = mid + 1; i <= r; ++i) {
for (int p : Q[i]) upd(p);
}
for (int i = l; i <= mid; ++i) {
for (int p : Q[i]) {
if (!query(p)) unite(e[p].u, e[p].v);
}
}
clr();
k = k << 1 | 1, cdq(mid + 1, r), k >>= 1;
revert();
}
int main() {
n = read(), m = read();
for (int i = 1; i <= m; ++i) {
e[i].u = read(), e[i].v = read();
}
q = read();
for (int i = 1; i <= q; ++i) {
int k = read(), x;
while (k--) {
x = read();
Q[i].push_back(x), upd(x);
}
}
tot = n;
for (int i = 1; i <= n; ++i) {
par[i] = i, sz[i] = 1;
}
for (int i = 1; i <= m; ++i) {
if (!query(i)) unite(e[i].u, e[i].v);
}
clr(), k = 1, cdq(1, q);
for (int i = 1; i <= q; ++i) {
puts(ans[i] ? "Connected" : "Disconnected");
}
return 0;
}