QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#641946 | #4046. 钥匙 | hos_lyric | 100 ✓ | 1584ms | 152404kb | C++14 | 10.9kb | 2024-10-15 03:50:56 | 2024-10-15 03:50:57 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
struct Hld {
int n, rt;
// needs to be tree
// vertex lists
// modified in build(rt) (parent removed, heavy child first)
vector<vector<int>> graph;
vector<int> sz, par, dep;
int zeit;
vector<int> dis, fin, sid;
// head vertex (minimum depth) in heavy path
vector<int> head;
Hld() : n(0), rt(-1), zeit(0) {}
explicit Hld(int n_) : n(n_), rt(-1), graph(n), zeit(0) {}
void ae(int u, int v) {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
graph[u].push_back(v);
graph[v].push_back(u);
}
void dfsSz(int u) {
sz[u] = 1;
for (const int v : graph[u]) {
auto it = std::find(graph[v].begin(), graph[v].end(), u);
if (it != graph[v].end()) graph[v].erase(it);
par[v] = u;
dep[v] = dep[u] + 1;
dfsSz(v);
sz[u] += sz[v];
}
}
void dfsHld(int u) {
dis[u] = zeit++;
const int deg = graph[u].size();
if (deg > 0) {
int vm = graph[u][0];
int jm = 0;
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
if (sz[vm] < sz[v]) {
vm = v;
jm = j;
}
}
swap(graph[u][0], graph[u][jm]);
head[vm] = head[u];
dfsHld(vm);
for (int j = 1; j < deg; ++j) {
const int v = graph[u][j];
head[v] = v;
dfsHld(v);
}
}
fin[u] = zeit;
}
void build(int rt_) {
assert(0 <= rt_); assert(rt_ < n);
rt = rt_;
sz.assign(n, 0);
par.assign(n, -1);
dep.assign(n, -1);
dep[rt] = 0;
dfsSz(rt);
zeit = 0;
dis.assign(n, -1);
fin.assign(n, -1);
head.assign(n, -1);
head[rt] = rt;
dfsHld(rt);
assert(zeit == n);
sid.assign(n, -1);
for (int u = 0; u < n; ++u) sid[dis[u]] = u;
}
friend ostream &operator<<(ostream &os, const Hld &hld) {
const int maxDep = *max_element(hld.dep.begin(), hld.dep.end());
vector<string> ss(2 * maxDep + 1);
int pos = 0, maxPos = 0;
for (int j = 0; j < hld.n; ++j) {
const int u = hld.sid[j];
const int d = hld.dep[u];
if (hld.head[u] == u) {
if (j != 0) {
pos = maxPos + 1;
ss[2 * d - 1].resize(pos, '-');
ss[2 * d - 1] += '+';
}
} else {
ss[2 * d - 1].resize(pos, ' ');
ss[2 * d - 1] += '|';
}
ss[2 * d].resize(pos, ' ');
ss[2 * d] += std::to_string(u);
if (maxPos < static_cast<int>(ss[2 * d].size())) {
maxPos = ss[2 * d].size();
}
}
for (int d = 0; d <= 2 * maxDep; ++d) os << ss[d] << '\n';
return os;
}
bool contains(int u, int v) const {
return (dis[u] <= dis[v] && dis[v] < fin[u]);
}
int lca(int u, int v) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
for (; head[u] != head[v]; ) (dis[u] > dis[v]) ? (u = par[head[u]]) : (v = par[head[v]]);
return (dis[u] > dis[v]) ? v : u;
}
int jumpUp(int u, int d) const {
assert(0 <= u); assert(u < n);
assert(d >= 0);
if (dep[u] < d) return -1;
const int tar = dep[u] - d;
for (u = head[u]; ; u = head[par[u]]) {
if (dep[u] <= tar) return sid[dis[u] + (tar - dep[u])];
}
}
int jump(int u, int v, int d) const {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
assert(d >= 0);
const int l = lca(u, v);
const int du = dep[u] - dep[l], dv = dep[v] - dep[l];
if (d <= du) {
return jumpUp(u, d);
} else if (d <= du + dv) {
return jumpUp(v, du + dv - d);
} else {
return -1;
}
}
// [u, v) or [u, v]
template <class F> void doPathUp(int u, int v, bool inclusive, F f) const {
assert(contains(v, u));
for (; head[u] != head[v]; u = par[head[u]]) f(dis[head[u]], dis[u] + 1);
if (inclusive) {
f(dis[v], dis[u] + 1);
} else {
if (v != u) f(dis[v] + 1, dis[u] + 1);
}
}
// not path order, include lca(u, v) or not
template <class F> void doPath(int u, int v, bool inclusive, F f) const {
const int l = lca(u, v);
doPathUp(u, l, false, f);
doPathUp(v, l, inclusive, f);
}
// (vs, ps): compressed tree
// vs: DFS order (sorted by dis)
// vs[ps[x]]: the parent of vs[x]
// ids[vs[x]] = x, not set for non-tree vertex
vector<int> ids;
pair<vector<int>, vector<int>> compress(vector<int> us) {
// O(n) first time
ids.resize(n, -1);
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
int usLen = us.size();
assert(usLen >= 1);
for (int x = 1; x < usLen; ++x) us.push_back(lca(us[x - 1], us[x]));
std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (dis[u] < dis[v]);
});
us.erase(std::unique(us.begin(), us.end()), us.end());
usLen = us.size();
for (int x = 0; x < usLen; ++x) ids[us[x]] = x;
vector<int> ps(usLen, -1);
for (int x = 1; x < usLen; ++x) ps[x] = ids[lca(us[x - 1], us[x])];
return make_pair(us, ps);
}
};
////////////////////////////////////////////////////////////////////////////////
template <class X, class Y, class T> struct StaticRectAddPointSum {
struct Rect {
X x0, x1;
Y y0, y1;
};
vector<Rect> as;
vector<pair<X, Y>> bs;
vector<T> vals, anss;
// Adds val to [x0, x1) [y0, y1).
// ~~> Adds to (x*, y*)
void add(X x0, X x1, Y y0, Y y1, const T &val) {
assert(x0 <= x1); assert(y0 <= y1);
as.push_back(Rect{x0, x1, y0, y1});
vals.push_back(val);
}
// Gets sum at (x, y).
void get(X x, Y y) {
bs.emplace_back(x, y);
}
void run() {
const int asLen = as.size(), bsLen = bs.size();
// same x ==> add then get
vector<pair<X, int>> events((asLen << 1) + bsLen);
for (int i = 0; i < asLen; ++i) {
events[i << 1 ] = std::make_pair(as[i].x0, i << 1 );
events[i << 1 | 1] = std::make_pair(as[i].x1, i << 1 | 1);
}
for (int j = 0; j < bsLen; ++j) {
events[(asLen << 1) + j] = std::make_pair(bs[j].first, (asLen << 1) + j);
}
std::sort(events.begin(), events.end());
vector<Y> ys(bsLen);
for (int j = 0; j < bsLen; ++j) {
ys[j] = bs[j].second;
}
std::sort(ys.begin(), ys.end());
ys.erase(std::unique(ys.begin(), ys.end()), ys.end());
const int ysLen = ys.size();
vector<T> bit(ysLen, 0);
anss.assign(bsLen, 0);
for (const auto &event : events) {
if (event.second >= asLen << 1) {
const int j = event.second - (asLen << 1);
T sum = 0;
for (int l = std::lower_bound(ys.begin(), ys.end(), bs[j].second) - ys.begin() + 1; l > 0; l &= l - 1) {
sum += bit[l - 1];
}
anss[j] = sum;
} else {
const int i = event.second >> 1;
const T val = (event.second & 1) ? -vals[i] : vals[i];
for (int l = std::lower_bound(ys.begin(), ys.end(), as[i].y0) - ys.begin(); l < ysLen; l |= l + 1) {
bit[l] += val;
}
for (int l = std::lower_bound(ys.begin(), ys.end(), as[i].y1) - ys.begin(); l < ysLen; l |= l + 1) {
bit[l] -= val;
}
}
}
}
};
////////////////////////////////////////////////////////////////////////////////
int N, Q;
vector<int> O, C;
vector<int> A, B;
vector<int> S, T;
Hld hld;
StaticRectAddPointSum<int, int, int> f;
// +1 point if S[q] -> s -> t -> T[q]
void add(int s, int t) {
const auto &L = hld.dis;
const auto &R = hld.fin;
assert(s != t);
if (hld.contains(s, t)) {
const int u = hld.jumpUp(t, hld.dep[t] - hld.dep[s] - 1);
f.add(0, L[u], L[t], R[t], +1);
f.add(R[u], N, L[t], R[t], +1);
} else if (hld.contains(t, s)) {
const int u = hld.jumpUp(s, hld.dep[s] - hld.dep[t] - 1);
f.add(L[s], R[s], 0, L[u], +1);
f.add(L[s], R[s], R[u], N, +1);
} else {
f.add(L[s], R[s], L[t], R[t], +1);
}
}
pair<vector<int>, vector<int>> vsps;
vector<vector<int>> graph;
void dfs(int c, int s, int x, int p, int d) {
const int u = vsps.first[x];
if (C[u] == c) {
if (O[u] == 1) {
++d;
} else {
if (--d == 0) {
// cerr<<"c = "<<c<<", s = "<<s<<", u = "<<u<<endl;
add(s, u);
return;
}
}
}
for (const int y : graph[x]) if (p != y) {
dfs(c, s, y, x, d);
}
}
int main() {
for (; ~scanf("%d%d", &N, &Q); ) {
O.resize(N);
C.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%d%d", &O[u], &C[u]);
--C[u];
}
A.resize(N - 1);
B.resize(N - 1);
for (int i = 0; i < N - 1; ++i) {
scanf("%d%d", &A[i], &B[i]);
--A[i];
--B[i];
}
S.resize(Q);
T.resize(Q);
for (int q = 0; q < Q; ++q) {
scanf("%d%d", &S[q], &T[q]);
--S[q];
--T[q];
}
hld = Hld(N);
for (int i = 0; i < N - 1; ++i) {
hld.ae(A[i], B[i]);
}
hld.build(0);
f = {};
vector<vector<int>> uss(N);
for (int u = 0; u < N; ++u) uss[C[u]].push_back(u);
for (int c = 0; c < N; ++c) if (uss[c].size()) {
vsps = hld.compress(uss[c]);
const int n = vsps.first.size();
graph.assign(n, {});
for (int y = 1; y < n; ++y) {
const int x = vsps.second[y];
graph[x].push_back(y);
graph[y].push_back(x);
}
for (const int u : uss[c]) if (O[u] == 1) {
dfs(c, u, hld.ids[u], -1, 0);
}
}
for (int q = 0; q < Q; ++q) {
f.get(hld.dis[S[q]], hld.dis[T[q]]);
}
f.run();
for (int q = 0; q < Q; ++q) {
printf("%d\n", f.anss[q]);
}
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Pretests
Final Tests
Test #1:
score: 10
Accepted
time: 1ms
memory: 4108kb
input:
100 100 2 1 2 5 2 5 2 1 2 5 1 3 2 1 1 5 2 6 2 2 1 6 2 1 1 1 2 1 2 6 1 5 2 3 2 6 1 7 2 4 2 4 1 7 2 4 2 6 2 6 2 5 1 2 1 5 2 3 2 3 2 1 2 2 1 4 1 2 2 3 2 3 2 1 1 7 2 3 2 2 2 6 2 3 1 3 2 6 2 3 2 2 2 5 2 5 2 5 2 5 1 5 2 1 2 5 2 4 2 4 2 4 2 1 1 2 2 3 1 3 2 4 2 2 2 1 2 1 2 3 1 4 1 4 1 1 1 2 2 3 2 2 2 3 2 4 ...
output:
0 0 0 2 0 0 1 0 0 0 0 1 2 0 0 0 0 0 0 1 1 1 2 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 2 0 1 1 0 0 2 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 2 0 1 0 0 0 1 0 0 0 0 1 0 0 2 0 0 0 0 1 0 0 1 0 0 3 0 0 0 0 0 0 1
result:
ok 100 numbers
Test #2:
score: 10
Accepted
time: 10ms
memory: 4804kb
input:
5000 5000 1 24 2 102 1 215 2 24 2 141 2 109 2 252 1 235 2 77 2 278 2 292 1 12 2 201 2 227 2 238 1 152 1 116 2 204 2 122 1 149 2 284 2 254 2 115 2 234 2 203 2 238 2 291 2 58 1 289 2 105 1 33 2 236 2 184 2 57 2 121 2 17 2 245 2 134 1 245 2 73 1 26 2 240 2 15 1 129 2 196 1 23 2 279 2 168 2 48 2 206 2 3...
output:
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 ...
result:
ok 5000 numbers
Test #3:
score: 10
Accepted
time: 9ms
memory: 4772kb
input:
5000 5000 2 230 2 243 2 77 2 149 2 298 2 176 1 103 2 131 1 127 2 110 1 115 1 220 1 23 2 259 2 290 2 77 2 211 2 249 2 232 2 163 2 55 2 277 2 148 2 171 2 14 2 226 2 70 1 194 1 269 2 277 2 4 2 107 1 246 2 226 2 79 2 219 1 21 2 203 2 4 2 129 2 87 1 114 2 180 2 37 2 202 2 5 2 39 1 28 2 168 2 35 1 184 2 1...
output:
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
result:
ok 5000 numbers
Test #4:
score: 10
Accepted
time: 137ms
memory: 27976kb
input:
100000 100000 2 56 1 2499 2 5148 2 2178 2 106 2 5422 2 2276 1 1085 2 1681 1 528 1 4743 2 3591 2 4902 2 5943 1 2664 2 5377 2 1923 2 195 2 1765 2 3177 2 3947 2 649 2 4772 2 3331 2 547 2 2908 2 4684 2 2741 2 5343 2 2494 2 3140 2 3823 1 1817 1 5225 2 3689 2 2768 2 6070 1 3584 1 2328 1 1506 2 4544 2 3323...
output:
5205 2591 208 3767 2284 3926 1985 438 1821 416 2614 3977 96 1397 2536 322 1682 100 396 1550 3809 1219 0 594 2058 169 860 2089 2549 5999 1837 2585 23 424 3309 371 383 4510 446 1975 967 547 1136 5210 2279 3656 0 126 1893 311 7977 454 4762 258 2000 2440 3498 2989 7478 2691 608 2620 5296 4403 4699 1925 ...
result:
ok 100000 numbers
Test #5:
score: 10
Accepted
time: 140ms
memory: 27288kb
input:
100000 100000 1 771 2 5185 2 1153 1 1611 2 2438 2 3680 2 5272 2 13 2 3069 2 3468 2 2209 2 6050 2 3287 2 1728 2 4981 2 1757 2 3630 2 1746 2 3057 1 726 2 2900 2 2033 2 2601 1 1478 2 214 1 5337 2 3948 2 1703 2 5112 2 5533 2 3558 2 1891 2 3887 2 2952 1 3425 1 177 1 1297 1 1916 2 1754 2 710 2 5212 1 1117...
output:
2149 1638 699 2224 2602 2596 401 1004 4 800 557 2105 3555 2186 2732 3767 1474 1972 3163 4410 2246 1899 1484 143 2349 388 1692 574 691 1414 3048 3147 1865 1487 1970 973 2104 1430 3776 618 750 887 3095 131 2560 3480 1730 3088 1026 3257 1164 122 3208 4370 3212 997 335 524 628 5280 1407 749 321 116 315 ...
result:
ok 100000 numbers
Test #6:
score: 10
Accepted
time: 918ms
memory: 118176kb
input:
500000 1000000 1 64861 1 119062 1 65144 1 143894 1 73264 2 33253 2 173191 2 52204 1 40950 2 71504 1 94677 2 28492 2 212348 2 155025 1 189945 2 71636 2 137081 2 129336 1 150409 2 200735 1 127414 2 155968 1 83751 2 29575 1 25125 1 111882 2 83939 1 64246 1 195870 1 14834 2 10887 2 98830 1 197278 2 1160...
output:
16 1 15 4 9 21 36 70 11 24 53 18 2 62 16 30 24 51 32 10 59 122 16 8 5 55 53 22 11 12 17 12 42 70 37 26 13 34 6 101 11 22 18 21 84 30 35 39 67 24 11 8 0 25 40 1 30 42 38 121 23 37 9 9 37 45 30 33 24 5 22 43 43 20 20 14 41 6 10 20 54 36 19 97 32 19 6 48 14 48 48 80 33 2 3 12 18 11 33 1 47 27 54 17 93 ...
result:
ok 1000000 numbers
Test #7:
score: 10
Accepted
time: 929ms
memory: 117996kb
input:
500000 1000000 2 99254 2 207080 2 40178 2 203616 2 143664 1 172563 1 235135 1 39267 2 34014 2 240014 2 122830 2 65547 1 190038 1 133892 1 195039 2 242508 1 16681 1 171326 1 179195 1 28872 2 91496 2 196836 1 12722 1 133176 1 49610 1 160238 2 137275 2 82747 2 22809 2 148101 2 18675 1 120676 1 86886 1 ...
output:
90 11 22 19 119 155 49 44 37 66 62 24 11 62 89 56 28 60 10 22 177 10 95 67 57 52 84 126 93 5 106 34 53 37 8 47 53 33 135 30 105 50 51 57 4 101 91 168 11 70 1 46 142 3 131 70 49 98 121 13 61 1 68 61 38 94 20 112 31 159 23 47 47 4 155 135 109 78 142 35 36 9 24 49 0 34 58 95 98 187 91 126 6 32 31 58 63...
result:
ok 1000000 numbers
Test #8:
score: 10
Accepted
time: 930ms
memory: 118288kb
input:
500000 1000000 1 89685 2 77808 2 60421 1 3478 1 174801 2 79073 1 171086 2 189510 2 141242 2 42469 2 197806 1 17953 2 165030 1 200212 2 65004 2 67818 2 86070 1 111422 1 229646 2 68851 1 14764 1 230949 2 71728 1 45456 1 5844 1 191082 1 54319 2 135488 2 24463 1 2976 2 226836 1 57817 2 45114 2 58082 1 3...
output:
21 33 31 22 54 59 25 2 38 39 7 42 45 132 98 12 18 24 5 34 38 36 4 11 41 14 36 36 18 2 33 8 35 42 28 8 13 64 18 41 12 29 67 32 6 34 26 22 33 80 39 66 8 11 84 52 45 120 74 53 9 37 28 59 65 36 29 11 4 38 18 10 6 66 20 22 38 32 21 27 12 37 35 22 29 37 31 6 39 33 38 13 36 68 39 21 77 28 46 38 33 30 12 7 ...
result:
ok 1000000 numbers
Test #9:
score: 10
Accepted
time: 1548ms
memory: 149744kb
input:
500000 1000000 1 6055 2 7862 2 1392 2 1440 2 15064 2 460 1 29587 2 3993 2 29185 2 29543 2 583 1 19479 2 28783 2 26722 1 17041 2 10894 2 3234 2 25053 1 15206 1 6122 2 25838 1 28948 2 25858 2 27787 2 19146 2 27381 2 20541 2 24645 1 16937 2 3163 2 3194 2 25925 2 11649 2 20379 1 7937 2 1913 2 18048 1 94...
output:
411 2 789 108 281 204 76 509 45 647 9 16 279 164 433 63 173 217 324 86 107 43 202 535 464 94 64 227 267 46 13 350 216 218 575 73 128 230 365 285 131 200 75 364 9 46 8 35 271 81 100 563 436 225 545 129 255 115 150 854 115 133 119 108 517 108 726 255 32 147 292 190 78 319 79 64 176 100 360 100 289 349...
result:
ok 1000000 numbers
Test #10:
score: 10
Accepted
time: 1584ms
memory: 152404kb
input:
500000 1000000 1 21782 1 23178 2 3615 1 22855 2 689 2 18959 2 17609 2 21923 1 28277 2 16406 2 7256 1 10175 2 25925 2 15485 2 25959 2 25908 1 20117 2 14563 1 25592 2 15719 1 9408 2 9539 1 28533 2 14576 2 2884 2 2701 1 13792 1 4222 2 21169 1 9207 2 17859 2 21128 1 3543 1 25941 2 4987 2 2529 2 20743 2 ...
output:
22 96 178 186 24 410 355 316 152 349 7 628 247 152 573 216 101 30 172 189 76 8 127 95 351 69 181 139 204 175 261 6 195 96 211 39 159 550 126 40 259 324 252 48 126 342 143 513 235 331 142 173 153 257 133 120 252 318 178 775 161 216 146 18 221 78 214 248 180 172 196 180 262 501 155 149 149 228 127 187...
result:
ok 1000000 numbers
Extra Test:
score: 0
Extra Test Passed