【 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 }
multiple

 

posted @ 2016-04-20 15:10  y7070  阅读(628)  评论(0编辑  收藏  举报