SPOJ COT 2 Count on a tree II(樹上莫隊)
26839 ワード
タイトルリンク:http://www.spoj.com/problems/COT2/
You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.
We will ask you to perfrom the following operation: u v : ask for how many different integers that represent the weight of nodes there are on the path from u to v.
Input
In the first line there are two integers N and M.(N<=40000,M<=100000)
In the second line there are N integers.The ith integer denotes the weight of the ith node.
In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).
In the next M lines,each line contains two integers u v,which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.
Output
For each operation,print its result.
1本の木に、各点に1つの重みがあります.パス(a,b)に何個の重み値が異なる点があるかを複数回尋ねる.
構想:VFK WC 2013キャンディパークパークパーク問題解(この問題はCOT 2より難しい.)
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
コード(2.37 S):
View Code
You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.
We will ask you to perfrom the following operation:
Input
In the first line there are two integers N and M.(N<=40000,M<=100000)
In the second line there are N integers.The ith integer denotes the weight of the ith node.
In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).
In the next M lines,each line contains two integers u v,which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.
Output
For each operation,print its result.
1本の木に、各点に1つの重みがあります.パス(a,b)に何個の重み値が異なる点があるかを複数回尋ねる.
構想:VFK WC 2013キャンディパークパークパーク問題解(この問題はCOT 2より難しい.)
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
コード(2.37 S):
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int MAXV = 40010;
5 const int MAXE = MAXV << 1;
6 const int MAXQ = 100010;
7 const int MLOG = 20;
8
9 namespace Bilibili {
10
11 int head[MAXV], val[MAXV], ecnt;
12 int to[MAXE], next[MAXE];
13 int n, m;
14
15 int stk[MAXV], top;
16 int block[MAXV], bcnt, bsize;
17
18 struct Query {
19 int u, v, id;
20 void read(int i) {
21 id = i;
22 scanf("%d%d", &u, &v);
23 }
24 void adjust() {
25 if(block[u] > block[v]) swap(u, v);
26 }
27 bool operator < (const Query &rhs) const {
28 if(block[u] != block[rhs.u]) return block[u] < block[rhs.u];
29 return block[v] < block[rhs.v];
30 }
31 } ask[MAXQ];
32 int ans[MAXQ];
33 /// Graph
34 void init() {
35 memset(head + 1, -1, n * sizeof(int));
36 ecnt = 0;
37 }
38
39 void add_edge(int u, int v) {
40 to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
41 to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
42 }
43
44 void gethash(int a[], int n) {
45 static int tmp[MAXV];
46 int cnt = 0;
47 for(int i = 1; i <= n; ++i) tmp[cnt++] = a[i];
48 sort(tmp, tmp + cnt);
49 cnt = unique(tmp, tmp + cnt) - tmp;
50 for(int i = 1; i <= n; ++i)
51 a[i] = lower_bound(tmp, tmp + cnt, a[i]) - tmp + 1;
52 }
53
54 void read() {
55 scanf("%d%d", &n, &m);
56 for(int i = 1; i <= n; ++i) scanf("%d", &val[i]);
57 gethash(val, n);
58 init();
59 for(int i = 1, u, v; i < n; ++i) {
60 scanf("%d%d", &u, &v);
61 add_edge(u, v);
62 }
63 for(int i = 0; i < m; ++i) ask[i].read(i);
64 }
65 /// find_block
66 void add_block(int &cnt) {
67 while(cnt--) block[stk[--top]] = bcnt;
68 bcnt++;
69 cnt = 0;
70 }
71
72 void rest_block() {
73 while(top) block[stk[--top]] = bcnt - 1;
74 }
75
76 int dfs_block(int u, int f) {
77 int size = 0;
78 for(int p = head[u]; ~p; p = next[p]) {
79 int v = to[p];
80 if(v == f) continue;
81 size += dfs_block(v, u);
82 if(size >= bsize) add_block(size);
83 }
84 stk[top++] = u;
85 size++;
86 if(size >= bsize) add_block(size);
87 return size;
88 }
89
90 void init_block() {
91 bsize = max(1, (int)sqrt(n));
92 dfs_block(1, 0);
93 rest_block();
94 }
95 /// ask_rmq
96 int fa[MLOG][MAXV];
97 int dep[MAXV];
98
99 void dfs_lca(int u, int f, int depth) {
100 dep[u] = depth;
101 fa[0][u] = f;
102 for(int p = head[u]; ~p; p = next[p]) {
103 int v = to[p];
104 if(v != f) dfs_lca(v, u, depth + 1);
105 }
106 }
107
108 void init_lca() {
109 dfs_lca(1, -1, 0);
110 for(int k = 0; k + 1 < MLOG; ++k) {
111 for(int u = 1; u <= n; ++u) {
112 if(fa[k][u] == -1) fa[k + 1][u] = -1;
113 else fa[k + 1][u] = fa[k][fa[k][u]];
114 }
115 }
116 }
117
118 int ask_lca(int u, int v) {
119 if(dep[u] < dep[v]) swap(u, v);
120 for(int k = 0; k < MLOG; ++k) {
121 if((dep[u] - dep[v]) & (1 << k)) u = fa[k][u];
122 }
123 if(u == v) return u;
124 for(int k = MLOG - 1; k >= 0; --k) {
125 if(fa[k][u] != fa[k][v])
126 u = fa[k][u], v = fa[k][v];
127 }
128 return fa[0][u];
129 }
130 /// modui
131 bool vis[MAXV];
132 int diff, cnt[MAXV];
133
134 void xorNode(int u) {
135 if(vis[u]) vis[u] = false, diff -= (--cnt[val[u]] == 0);
136 else vis[u] = true, diff += (++cnt[val[u]] == 1);
137 }
138
139 void xorPathWithoutLca(int u, int v) {
140 if(dep[u] < dep[v]) swap(u, v);
141 while(dep[u] != dep[v])
142 xorNode(u), u = fa[0][u];
143 while(u != v)
144 xorNode(u), u = fa[0][u],
145 xorNode(v), v = fa[0][v];
146 }
147
148 void moveNode(int u, int v, int taru, int tarv) {
149 xorPathWithoutLca(u, taru);
150 xorPathWithoutLca(v, tarv);
151 //printf("debug %d %d
", ask_lca(u, v), ask_lca(taru, tarv));
152 xorNode(ask_lca(u, v));
153 xorNode(ask_lca(taru, tarv));
154 }
155
156 void make_ans() {
157 for(int i = 0; i < m; ++i) ask[i].adjust();
158 sort(ask, ask + m);
159 int nowu = 1, nowv = 1; xorNode(1);
160 for(int i = 0; i < m; ++i) {
161 moveNode(nowu, nowv, ask[i].u, ask[i].v);
162 ans[ask[i].id] = diff;
163 nowu = ask[i].u, nowv = ask[i].v;
164 }
165 }
166
167 void print_ans() {
168 for(int i = 0; i < m; ++i)
169 printf("%d
", ans[i]);
170 }
171
172 void solve() {
173 read();
174 init_block();
175 init_lca();
176 make_ans();
177 print_ans();
178 }
179
180 };
181
182 int main() {
183 Bilibili::solve();
184 }
View Code