【 bzoj4537】HNOI2016 最小公倍数
首先将边按a的值分组,每$\sqrt{m}$一组。
对于每一组,将符合一组a的询问选出来,将这些询问和这一块之前的边(a一定小于这些询问)按b排序,然后交替插入,询问,对于一个询问,在当前块也有可能有满足的边,我们将其加入,考虑后并撤销,由于块大小是$\sqrt{m}$所以复杂度正确。
注意 : 1.并查集不能路径压缩,否则无法撤销;
2.在筛选一组的询问时,不要让一个询问被考虑多次,也就是说用询问的a小于终点后的那条边的a作为筛选条件,否则假如所有的a一样,那么每个询问每次都会被考虑一遍。
复杂度为$\sqrt{m}mlog(m) + Q \sqrt{m}$
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define xx first 8 #define yy second 9 using namespace std; 10 typedef long long ll; 11 typedef pair<int, int> pii; 12 const int inf = 0x3f3f3f3f; 13 const ll INF = 0x3f3f3f3f3f3f3f3fll; 14 template <typename T> void Max(T& a, T b) { if (b > a) a = b; } 15 //********************************* 16 17 const int maxn = 50005, maxm = 100005; 18 struct DATA { 19 int u, v, a, b, id; 20 } e[maxm], q[maxn], tmp[maxn]; 21 bool cmpa(DATA a, DATA b) { return a.a < b.a; } 22 bool cmpb(DATA a, DATA b) { return a.b < b.b; } 23 24 struct Option { 25 int x, y, xmaxa, xmaxb, sz, ymaxa, ymaxb, f; Option() {} 26 Option(int _x, int _y, int _xmaxa, int _xmaxb, int _sz, int _ymaxa, int _ymaxb, int _f) : 27 x(_x), y(_y), xmaxa(_xmaxa), xmaxb(_xmaxb), sz(_sz), ymaxa(_ymaxa), ymaxb(_ymaxb), f(_f) {} 28 } op[maxn]; 29 30 int top; 31 int fa[maxn], sz[maxn], maxa[maxn], maxb[maxn]; 32 int ans[maxn]; 33 int getfather(int x) { return fa[x] == x ? x : getfather(fa[x]); } 34 void merge(int x, int y, int a, int b) { 35 int fx = getfather(x), fy = getfather(y); 36 if (sz[fx] < sz[fy]) swap(fx, fy); 37 op[++top] = (Option){fx, fy, maxa[fx], maxb[fx], sz[fx], maxa[fy], maxb[fy], fa[fy]}; 38 if (fx == fy) { 39 maxa[fx] = max(maxa[fx], a); 40 maxb[fx] = max(maxb[fx], b); 41 return; 42 } 43 sz[fx] += sz[fy]; 44 maxa[fx] = max(maxa[fx], max(maxa[fy], a)); 45 maxb[fx] = max(maxb[fx], max(maxb[fy], b)); 46 fa[fy] = fx; 47 } 48 49 void retrace() { 50 drep(i, top, 1) { 51 maxa[op[i].x] = op[i].xmaxa; 52 maxb[op[i].x] = op[i].xmaxb; 53 maxa[op[i].y] = op[i].ymaxa; 54 maxb[op[i].y] = op[i].ymaxb; 55 fa[op[i].y] = op[i].f; 56 sz[op[i].x] = op[i].sz; 57 } 58 } 59 60 int main() { 61 /* 62 freopen("multiple.in", "r", stdin); 63 freopen("multiple.out", "w", stdout); 64 */ 65 int n, m; scanf("%d%d", &n, &m); 66 rep(i, 1, m) scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].a, &e[i].b); 67 int Q; scanf("%d", &Q); 68 rep(i, 1, Q) scanf("%d%d%d%d", &q[i].u, &q[i].v, &q[i].a, &q[i].b), q[i].id = i; 69 int Sz = sqrt(m); 70 71 sort(e + 1, e + 1 + m, cmpa); 72 sort(q + 1, q + 1 + Q, cmpb); 73 74 for (int st = 1; st <= m; st += Sz) { 75 int end = min(st + Sz - 1, m); 76 77 int cnt(0); 78 for (int i = 1; i <= Q; i++) if (q[i].a >= e[st].a && (st + Sz > m || q[i].a < e[end + 1].a)) tmp[++cnt] = q[i]; 79 if (!cnt) continue; 80 81 sort(e + 1, e + st, cmpb); 82 83 rep(i, 1, n) fa[i] = i, sz[i] = 1, maxa[i] = maxb[i] = -1; 84 for (int k = 1, j = 1; k <= cnt; k++) { 85 while (e[j].b <= tmp[k].b && j < st) merge(e[j].u, e[j].v, e[j].a, e[j].b), j++; 86 87 top = 0; 88 rep(i, st, end) if (e[i].a <= tmp[k].a && e[i].b <= tmp[k].b) merge(e[i].u, e[i].v, e[i].a, e[i].b); 89 int fx = getfather(tmp[k].u), fy = getfather(tmp[k].v); 90 if (fa[fx] == fa[fy] && maxa[fx] == tmp[k].a && maxb[fx] == tmp[k].b) ans[tmp[k].id] = 1; 91 retrace(); 92 } 93 94 } 95 rep(i, 1, Q) if (ans[i]) puts("Yes"); else puts("No"); 96 97 return 0; 98 }