关于矩形与点其实有两种关系。
一种是每个矩形包含多少点。一种是每个点被多少矩形包含。
解:因为可以离线所以直接套整体二分。关键是考虑如何能够被覆盖。
我一开始都是想的树上操作...其实是转化成DFS序。分链和有lca两种情况。
考虑每个盘子能接住的水果,两端DFS序满足的性质。发现是二维平面上的矩形。
一个水果就是询问一个点被多少矩形覆盖(能被多少盘子接)。于是整体二分里面扫描线,片改点查用树状数组。
1 #include2 3 const int N = 80010; 4 5 struct Edge { 6 int nex, v; 7 }edge[N << 1]; int tp; 8 9 int e[N], pos[N], ed[N], num, n, fa[N][20], pw[N], d[N]; /// tree 10 int X[N], xx, ans[N]; 11 12 struct Node { 13 int id, x, y, k, z; 14 Node(int ID = 0, int X = 0, int Y = 0, int K = 0, int Z = 0) { 15 id = ID; 16 x = X; 17 y = Y; 18 k = K; 19 z = Z; 20 } 21 inline bool operator <(const Node &w) const { 22 if(id != w.id) return id < w.id; 23 return z < w.z; 24 } 25 }node[N], t1[N], t2[N], stk[N << 2]; 26 27 namespace ta { 28 int ta[N]; 29 inline void add(int x, int v) { 30 for(int i = x; i <= n + 1; i += (i & (-i))) { 31 ta[i] += v; 32 } 33 return; 34 } 35 inline int ask(int x) { 36 int ans = 0; 37 for(int i = x; i >= 1; i -= (i & (-i))) { 38 ans += ta[i]; 39 } 40 return ans; 41 } 42 inline void del(int x) { 43 for(int i = x; i <= n + 1; i += (i & (-i))) { 44 ta[i] = 0; 45 } 46 return; 47 } 48 } 49 50 inline void add(int x, int y) { 51 tp++; 52 edge[tp].v = y; 53 edge[tp].nex = e[x]; 54 e[x] = tp; 55 return; 56 } 57 58 void DFS(int x, int f) { 59 pos[x] = ++num; 60 fa[x][0] = f; 61 d[x] = d[f] + 1; 62 for(int i = e[x]; i; i = edge[i].nex) { 63 int y = edge[i].v; 64 if(y == f) continue; 65 DFS(y, x); 66 } 67 ed[x] = num; 68 return; 69 } 70 71 inline void prework() { 72 for(int i = 2; i <= n; i++) pw[i] = pw[i >> 1] + 1; 73 for(int j = 1; j <= pw[n]; j++) { 74 for(int i = 1; i <= n; i++) { 75 fa[i][j] = fa[fa[i][j - 1]][j - 1]; 76 } 77 } 78 return; 79 } 80 81 inline int lca(int x, int y) { 82 if(d[x] > d[y]) std::swap(x, y); 83 int t = pw[n]; 84 while(t >= 0 && d[y] > d[x]) { 85 if(d[fa[y][t]] >= d[x]) { 86 y = fa[y][t]; 87 } 88 t--; 89 } 90 if(x == y) return x; 91 t = pw[n]; 92 while(t >= 0 && fa[x][0] != fa[y][0]) { 93 if(fa[x][t] != fa[y][t]) { 94 x = fa[x][t]; 95 y = fa[y][t]; 96 } 97 t--; 98 } 99 return fa[x][0]; 100 } 101 102 inline int getPos(int x, int y) { 103 int t = pw[n]; 104 while(t >= 0 && fa[y][0] != x) { 105 if(d[fa[y][t]] > d[x]) { 106 y = fa[y][t]; 107 } 108 t--; 109 } 110 return y; 111 } 112 113 void Div(int L, int R, int l, int r) { 114 if(L > R) return; 115 if(l == r) { 116 for(int i = L; i <= R; i++) { 117 if(node[i].id) ans[node[i].id] = r; 118 } 119 return; 120 } 121 122 int mid = (l + r) >> 1, top1 = 0, top2 = 0, top = 0; 123 for(int i = L; i <= R; i++) { 124 int x = node[i].x, y = node[i].y, z = node[i].z; 125 if(!node[i].id) { /// change | this is a Matrix 126 if(node[i].k > mid) { 127 t2[++top2] = node[i]; 128 continue; 129 } 130 t1[++top1] = node[i]; 131 if(z) { /// line 132 stk[++top] = Node(1, pos[y], ed[y], 1, 0); 133 stk[++top] = Node(pos[z], pos[y], ed[y], -1, 0); 134 stk[++top] = Node(pos[y], ed[z] + 1, n, 1, 0); 135 stk[++top] = Node(ed[y] + 1, ed[z] + 1, n, -1, 0); 136 } 137 else { /// lca 138 stk[++top] = Node(pos[x], pos[y], ed[y], 1, 0); 139 stk[++top] = Node(ed[x] + 1, pos[y], ed[y], -1, 0); 140 } 141 } 142 else { /// ask | this is a Point 143 stk[++top] = Node(pos[x], 0, pos[y], i, 1); 144 } 145 } 146 std::sort(stk + 1, stk + top + 1); 147 for(int i = 1; i <= top; i++) { 148 if(stk[i].z == 0) { /// change 149 ta::add(stk[i].x, stk[i].k); 150 ta::add(stk[i].y + 1, -stk[i].k); 151 } 152 else { /// ask 153 int t = ta::ask(stk[i].y), id = stk[i].k; 154 if(node[id].k <= t) { 155 t1[++top1] = node[id]; 156 } 157 else { 158 node[id].k -= t; 159 t2[++top2] = node[id]; 160 } 161 } 162 } 163 for(int i = 1; i <= top; i++) { /// clear 164 if(stk[i].z == 0) { 165 ta::del(stk[i].x); 166 ta::del(stk[i].y + 1); 167 } 168 } 169 memcpy(node + L, t1 + 1, top1 * sizeof(Node)); 170 memcpy(node + L + top1, t2 + 1, top2 * sizeof(Node)); 171 Div(L, L + top1 - 1, l, mid); 172 Div(L + top1, R, mid + 1, r); 173 return; 174 } 175 176 int main() { 177 int m, q; 178 scanf("%d%d%d", &n, &m, &q); 179 for(int i = 1, x, y; i < n; i++) { 180 scanf("%d%d", &x, &y); 181 add(x, y); add(y, x); 182 } 183 DFS(1, 0); 184 prework(); 185 for(int i = 1, x, y, z; i <= m; i++) { 186 scanf("%d%d%d", &x, &y, &X[i]); 187 if(pos[x] > pos[y]) std::swap(x, y); 188 z = lca(x, y); 189 node[i] = Node(0, x, y, X[i], (z == x) ? getPos(x, y) : 0); 190 } 191 std::sort(X + 1, X + n + 1); 192 xx = std::unique(X + 1, X + n + 1) - X - 1; 193 for(int i = 1; i <= m; i++) { 194 node[i].k = std::lower_bound(X + 1, X + xx + 1, node[i].k) - X; 195 } 196 for(int i = 1, x, y, k; i <= q; i++) { 197 scanf("%d%d%d", &x, &y, &k); 198 if(pos[x] > pos[y]) std::swap(x, y); 199 node[m + i] = Node(i, x, y, k, 0); 200 } 201 Div(1, m + q, 1, xx); 202 for(int i = 1; i <= q; i++) printf("%d\n", X[ans[i]]); 203 return 0; 204 }