11-22模拟赛

11 / 22 / 2020 | 最后修改于 11 / 22 / 2020

Dash Speed

题目描述

比特山是比特镇的飙车圣地。在比特山上一共有 nn 个广场,编号依次为 11nn,这些广场之间通过 n1n-1 条双向车道直接或间接地连接在一起,形成了一棵树的结构。

因为每条车道的修建时间以及建筑材料都不尽相同,所以可以用两个数字 li,ril_i,r_i 量化地表示一条车道的承受区间,只有当汽车以不小于 lil_i 且不大于 rir_i 的速度经过这条车道时,才不会对路面造成伤害。

Byteasar 最近新买了一辆跑车,他想在比特山飙一次车。Byteasar 计划选择两个不同的点 STS,T 然后在它们树上的最短路径上行驶,且不对上面任意一条车道造成伤害。

Byteasar 不喜欢改变速度,所以他会告诉你他的车速。为了挑选出最合适的车速,Byteasar 一共会向你询问 mm 次。请帮助他找到一条合法的道路,使得路径上经过的车道数尽可能多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>

template <typename T>
inline T& read(T& x) {
x = 0;
bool f = false;
short ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') f = true;
ch = getchar();
}
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ '0'), ch = getchar();
if (f) x = -x;
return x;
}

const int N = 7e4 + 5;
int n, m, heads[N], e_cnt, dep[N], siz[N], fa[N], son[N], top[N], ans[N];

struct Edge {
int nxt, v;
Edge() {}
Edge(int u, int v) : nxt(u), v(v) {}
} e[N << 1];

void add(int u, int v) {
e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
}

void dfs1(int u, int f) {
fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
for (int j = heads[u], v; j; j = e[j].nxt)
if ((v = e[j].v) != f) {
dfs1(v, u), siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
}

void dfs2(int u, int Top) {
top[u] = Top;
if (son[u]) dfs2(son[u], Top);
for (int j = heads[u], v; j; j = e[j].nxt)
if ((v = e[j].v) != fa[u] && v != son[u]) dfs2(v, v);
}

inline int getlca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}

inline int getdis(int x, int y) {
return dep[x] + dep[y] - (dep[getlca(x, y)] << 1);
}

struct Node {
int a, b, w;
Node() {}
Node(int a, int b, int w) : a(a), b(b), w(w) {}

inline void operator()(const Node& rhs) {
int tmp = getdis(a, rhs.a), orib = this->b;
if (w < tmp) this->b = rhs.a, this->w = tmp;
tmp = getdis(a, rhs.b);
if (w < tmp) this->b = rhs.b, this->w = tmp;
tmp = getdis(orib, rhs.a);
if (w < tmp) this->a = orib, this->b = rhs.a, this->w = tmp;
tmp = getdis(orib, rhs.b);
if (w < tmp) this->a = orib, this->b = rhs.b, this->w = tmp;
if (w < rhs.w) *this = rhs;
}
};

struct Segtree {
struct UFSNode {
Node s;
int fa, dep;
} p[N];

struct Node {
int u;
UFSNode p0;
Node(int u, const UFSNode& p0) : u(u), p0(p0) {}
};

std::vector<Edge> E[N << 2];
std::stack<Node> stk;

void insert(int x, int l, int r, int L, int R, const Edge& e) {
if (L <= l && r <= R) return E[x].emplace_back(e);
int mid = (l + r) >> 1;
if (L <= mid) insert(x << 1, l, mid, L, R, e);
if (mid < R) insert(x << 1 | 1, mid + 1, r, L, R, e);
}

int find(int u) { return u == p[u].fa ? u : find(p[u].fa); }

inline void merge(int u, int v, int& len) {
u = find(u), v = find(v);
if (u == v) return;
if (p[u].dep > p[v].dep) std::swap(u, v);
stk.push(Node(u, p[u])), stk.push(Node(v, p[v]));
p[v].s(p[u].s), p[u].fa = v;
if (p[u].dep == p[v].dep) ++p[v].dep;
len = std::max(len, p[v].s.w);
}

void solve(int x, int l, int r, int len) {
size_t ori = stk.size();
for (auto& i : E[x]) merge(i.nxt, i.v, len);
if (l == r) ans[l] = len;
else {
int mid = (l + r) >> 1;
solve(x << 1, l, mid, len);
solve(x << 1 | 1, mid + 1, r, len);
}
while (stk.size() != ori) {
p[stk.top().u] = stk.top().p0;
stk.pop();
}
}
} seg;

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
freopen64("/tmp/CodeTmp/testdata.in", "r", stdin);
freopen64("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
freopen("External.in", "r", stdin);
freopen("External.out", "w", stdout);
#endif
#endif

read(n), read(m);
for (int i = 1, u, v, l, r; i < n; ++i) {
read(u), read(v), read(l), read(r);
add(u, v), add(v, u);
seg.insert(1, 1, n, l, r, Edge(u, v));
}
dfs1(1, 0), dfs2(1, 1);
for (int i = 1; i <= n; ++i)
seg.p[i].fa = i, seg.p[i].dep = 1, seg.p[i].s = Node(i, i, 0);
seg.solve(1, 1, n, 0);
for (int i = 1, x; i <= m; ++i) printf("%d\n", ans[read(x)]);
return 0;
}