UOJ 407(IOI2018 D1T3)
给定一张$n$个点,$m$条边的无向连通图以及$q$次询问,每次询问给出$S,E,L,R$,问你是否能从$S$出发,不经过编号小于$L$的点到达某个编号大于等于$L$且小于等于$R$的点,此时切换状态,不经过编号大于$R$的点到达$E$。
$$n\le200000,m\le400000,q\le200000$$
这种有限制的连通性问题一般考虑Kruskal重构树,对两个限制建出两棵树,倍增找出每个询问能到达的点的区间,然后就是一个经典的二维数点问题了,排序后树状数组解决。
1 constexpr int MAXN = 200000 + 5, MAXM = 400000 + 5, LOG = 20; 2 3 int lg[MAXN * 2]; 4 5 struct Tree { 6 static constexpr int MAX_N = MAXM; 7 8 int hed[MAX_N], nxt[MAX_N * 2], to[MAX_N * 2], val[MAX_N], fa[LOG][MAX_N], dep[MAX_N], L[MAX_N], R[MAX_N], cnt, num; 9 10 void addEdge(int u, int v) { 11 ++ cnt; 12 to[cnt] = v; 13 nxt[cnt] = hed[u]; 14 hed[u] = cnt; 15 } 16 17 void DFS(int u, int total) { 18 for (int i = 1; 1 << i <= dep[u]; ++ i) { 19 fa[i][u] = fa[i - 1][fa[i - 1][u]]; 20 } 21 if (u <= total) { 22 L[u] = R[u] = ++ num; 23 } else { 24 L[u] = INF, R[u] = 0; 25 } 26 for (int e = hed[u]; e; e = nxt[e]) { 27 int v = to[e]; 28 if (v != fa[0][u]) { 29 fa[0][v] = u; 30 dep[v] = dep[u] + 1; 31 DFS(v, total); 32 chkmin(L[u], L[v]); 33 chkmax(R[u], R[v]); 34 } 35 } 36 } 37 38 int find(int u, int w, const std::function<bool(int, int)> &comp) { 39 Rep(i, lg[dep[u]], 0) { 40 if (fa[i][u] && comp(val[fa[i][u]], w)) { 41 u = fa[i][u]; 42 } 43 } 44 return u; 45 } 46 } T1, T2; 47 48 struct DSU { 49 int fa[MAXN], bel[MAXN]; 50 51 void init(int n) { 52 For(i, 1, n) { 53 fa[i] = bel[i] = i; 54 } 55 } 56 57 int find(int u) { 58 return fa[u] == u ? u : fa[u] = find(fa[u]); 59 } 60 61 bool same(int u, int v) { 62 return find(u) == find(v); 63 } 64 65 void merge(int u, int v, int x) { 66 if (!same(u, v)) { 67 fa[fa[v]] = fa[u], bel[fa[u]] = x; 68 } 69 } 70 } U; 71 72 struct BinaryIndexedTree { 73 int a[MAXN], length; 74 75 #define lowbit(x) ((x) & -(x)) 76 void init(int n) { 77 length = n; 78 } 79 80 void modify(int i, int x) { 81 for (; i <= length; i += lowbit(i)) { 82 a[i] += x; 83 } 84 } 85 86 int query(int i) { 87 int result = 0; 88 for (; i; i -= lowbit(i)) { 89 result += a[i]; 90 } 91 return result; 92 } 93 #undef lowbit 94 } BIT; 95 96 IL void adjust(std::vector<int> &v) { 97 for (auto &x : v) { 98 ++ x; 99 } 100 } 101 102 std::vector<int> check_validity(int N, std::vector<int> X, std::vector<int> Y, 103 std::vector<int> S, std::vector<int> E, 104 std::vector<int> L, std::vector<int> R) { 105 adjust(X), adjust(Y), adjust(S), adjust(E), adjust(L), adjust(R); 106 std::vector<std::pair<int, int>> edge(X.size()); 107 FOR(i, 0, (int)edge.size()) { 108 edge[i] = std::make_pair(X[i], Y[i]); 109 } 110 lg[0] = -1; 111 FOR(i, 1, N << 1) { 112 lg[i] = lg[i >> 1] + 1; 113 } 114 int Q = S.size(); 115 std::vector<int> answer(Q); 116 static bool ok[MAXN]; 117 memset(ok, 1, sizeof ok); 118 FOR(i, 0, Q) { 119 if (S[i] < L[i] || E[i] > R[i]) { 120 ok[i] = 0; 121 } 122 } 123 static std::vector<int> left[MAXN], right[MAXN]; 124 std::sort(edge.begin(), edge.end(), [](const std::pair<int, int> &a, const std::pair<int, int> &b) -> bool { 125 return mymin(a.first, a.second) > mymin(b.first, b.second); 126 }); 127 U.init(N); 128 For(i, 1, N) { 129 T1.val[i] = i; 130 } 131 int cnt = 0; 132 for (auto &x : edge) { 133 if (!U.same(x.first, x.second)) { 134 ++ cnt; 135 int p = U.fa[x.first], q = U.fa[x.second]; 136 T1.val[N + cnt] = mymin(T1.val[U.bel[p]], T1.val[U.bel[q]]); 137 T1.addEdge(U.bel[p], N + cnt); 138 T1.addEdge(N + cnt, U.bel[p]); 139 T1.addEdge(U.bel[q], N + cnt); 140 T1.addEdge(N + cnt, U.bel[q]); 141 U.merge(x.first, x.second, N + cnt); 142 } 143 if (cnt >= N - 1) { 144 break; 145 } 146 } 147 T1.DFS((N << 1) - 1, N); 148 FOR(i, 0, Q) { 149 if (!ok[i]) { 150 continue; 151 } 152 int u = T1.find(S[i], L[i], [](int a, int b) -> bool { 153 return a >= b; 154 }); 155 left[T1.L[u]].push_back(i); 156 right[T1.R[u]].push_back(i); 157 } 158 std::sort(edge.begin(), edge.end(), [](const std::pair<int, int> &a, const std::pair<int, int> &b) -> bool { 159 return mymax(a.first, a.second) < mymax(b.first, b.second); 160 }); 161 U.init(N); 162 For(i, 1, N) { 163 T2.val[i] = i; 164 } 165 cnt = 0; 166 for (auto &x : edge) { 167 if (!U.same(x.first, x.second)) { 168 ++ cnt; 169 int p = U.fa[x.first], q = U.fa[x.second]; 170 T2.val[N + cnt] = mymax(T2.val[U.bel[p]], T2.val[U.bel[q]]); 171 T2.addEdge(U.bel[p], N + cnt); 172 T2.addEdge(N + cnt, U.bel[p]); 173 T2.addEdge(U.bel[q], N + cnt); 174 T2.addEdge(N + cnt, U.bel[q]); 175 U.merge(x.first, x.second, N + cnt); 176 } 177 if (cnt >= N - 1) { 178 break; 179 } 180 } 181 T2.DFS((N << 1) - 1, N); 182 std::vector<std::pair<int, int>> interval(Q); 183 FOR(i, 0, Q) { 184 if (!ok[i]) { 185 continue; 186 } 187 int u = T2.find(E[i], R[i], [](int a, int b) -> bool { 188 return a <= b; 189 }); 190 interval[i] = std::make_pair(T2.L[u], T2.R[u]); 191 } 192 static std::vector<int> point[MAXN]; 193 For(i, 1, N) { 194 point[T1.L[i]].push_back(T2.L[i]); 195 } 196 BIT.init(N); 197 For(i, 1, N) { 198 for (auto &x : left[i]) { 199 answer[x] = BIT.query(interval[x].second) - BIT.query(interval[x].first - 1); 200 } 201 for (auto &x : point[i]) { 202 BIT.modify(x, 1); 203 } 204 for (auto &x : right[i]) { 205 answer[x] = !!(BIT.query(interval[x].second) - BIT.query(interval[x].first - 1) - answer[x]); 206 } 207 } 208 return answer; 209 }