树上的莫队算法。。。话说糖果公园也是的说?、、、蒟蒻不会233
先搞出dfs序,然后对dfs序直接莫队就好了。。。
但是写的我蛋疼啊。。。3h就一道题还让不让人活?
1 /************************************************************** 2 Problem: 3757 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4000 ms 7 Memory:23096 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <cmath> 13 #include <algorithm> 14 15 using namespace std; 16 const int N = 100005; 17 const int Maxlen = 3500005; 18 19 int n, Q; 20 int tot, first[N]; 21 int dfn, c[N], w[N << 1]; 22 int sz, pos[N << 1]; 23 int l, r, Lca; 24 int sum, cnt[N], ans[N]; 25 bool vis[N << 1]; 26 char buf[Maxlen], *C = buf; 27 int Len; 28 29 struct tree_node { 30 int dep, fa[20]; 31 bool vis; 32 int st, en; 33 } tr[N]; 34 35 struct edges { 36 int next, to; 37 edges() {} 38 edges(int _n, int _t) : next(_n), to(_t) {} 39 } e[N << 1]; 40 41 struct query { 42 int l, r, lca, a, b, id; 43 44 inline bool operator < (const query &b) const { 45 return pos[l] == pos[b.l] ? r < b.r : pos[l] < pos[b.l]; 46 } 47 }a[N]; 48 49 void Add_Edges(int x, int y) { 50 e[++tot] = edges(first[x], y), first[x] = tot; 51 e[++tot] = edges(first[y], x), first[y] = tot; 52 } 53 54 inline int read() { 55 int x = 0; 56 while (*C < '0' || '9' < *C) ++C; 57 while ('0' <= *C && *C <= '9') 58 x = x * 10 + *C - '0', ++C; 59 return x; 60 } 61 62 void dfs(int p) { 63 int x, y; 64 w[tr[p].st = ++dfn] = p, tr[p].vis = 1; 65 for (x = 1; x <= 17; ++x) 66 tr[p].fa[x] = tr[tr[p].fa[x - 1]].fa[x - 1]; 67 for (x = first[p]; x; x = e[x].next) 68 if (!tr[y = e[x].to].vis) 69 tr[y].dep = tr[p].dep + 1, tr[y].fa[0] = p, dfs(y); 70 w[tr[p].en = ++dfn] = p; 71 } 72 73 inline int lca(int x, int y) { 74 int i; 75 if (x == y) return x; 76 if (tr[x].dep < tr[y].dep) swap(x, y); 77 for (i = 17; i >= 0; --i) 78 if (tr[tr[x].fa[i]].dep >= tr[y].dep) x = tr[x].fa[i]; 79 if (x == y) return x; 80 for (i = 17; i >= 0; --i) 81 if (tr[x].fa[i] != tr[y].fa[i]) x = tr[x].fa[i], y = tr[y].fa[i]; 82 return tr[x].fa[0]; 83 } 84 85 inline int check(int x, int y) { 86 return x != y && cnt[x] && cnt[y]; 87 } 88 89 inline void update(int x) { 90 if (vis[x]) { 91 if (!(--cnt[c[x]])) --sum; 92 } else 93 if (!(cnt[c[x]]++)) ++sum; 94 vis[x] ^= 1; 95 } 96 97 int main() { 98 Len = fread(C, 1, Maxlen, stdin); 99 buf[Len] = '\0'; 100 int i, x, y; 101 n = read(), Q = read(); 102 for (i = 1; i <= n; ++i) 103 c[i] = read(); 104 for (i = 1; i <= n; ++i) { 105 x = read(), y = read(); 106 if (x && y) Add_Edges(x, y); 107 } 108 tr[1].dep = 1; 109 dfs(1); 110 111 sz = (int) sqrt(n * 2 + 0.5); 112 for (i = 1; i <= dfn; ++i) 113 pos[i] = (i - 1) / sz + 1; 114 for (i = 1; i <= Q; ++i) { 115 x = read(), y = read(); 116 a[i].a = read(), a[i].b = read(), a[i].id = i; 117 if (tr[x].st > tr[y].st) swap(x, y); 118 Lca = lca(x, y); 119 if (Lca == x) 120 a[i].l = tr[x].st, a[i].r = tr[y].st; 121 else a[i].l = tr[x].en, a[i].r = tr[y].st, a[i].lca = Lca; 122 } 123 124 sort(a + 1, a + Q + 1); 125 for (i = 1, l = 1, r = 0; i <= Q; ++i) { 126 while (r < a[i].r) update(w[++r]); 127 while (r > a[i].r) update(w[r--]); 128 while (l < a[i].l) update(w[l++]); 129 while (l > a[i].l) update(w[--l]); 130 if (a[i].lca) update(a[i].lca); 131 ans[a[i].id] = sum - check(a[i].a, a[i].b); 132 if (a[i].lca) update(a[i].lca); 133 } 134 for (i = 1; i <= Q; ++i) 135 printf("%d\n", ans[i]); 136 return 0; 137 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen