C. 【XR-3】核心城市
树直径签到题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
vector<int> G[maxn];
int dep[maxn], rt, o, dp[maxn];
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
dp[u] = 1;
if (dep[u] > dep[rt])
rt = u;
for (auto v : G[u])
if (v != fa) {
dfs(v, u);
dp[u] = max(dp[u], dp[v] + 1);
}
if (dp[u] == (dep[rt] + 1) / 2)
o = u;
}
int main() {
int n, k, u, v;
scanf("%d%d", &n, &k);
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0);
dfs(rt, 0);
dfs(o, 0);
sort(dp + 1, dp + 1 + n);
printf("%d\n", dp[n - k]);
}
D.【XR-3】系统设计
解法:我们先对每个节点的出边按儿子的编号排序,然后每个儿子都会得到一个顺序
k,将树重链剖分,每个点对应的
hash值是重儿子顺序
k∗p[dfn],然后维护每条重链的
hash值,同时用树状数组动态维护
a序列
hash值,每次查询操作,我们从
x节点,顺着它的重链通过hash二分找到其与
a序列的
lcp,然后我们跳到
lcp的那个节点继续操作即可。明天再试试线段树解法
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define low(x) x&-x
using namespace std;
const int maxn = 5e5 + 10, base = 998244353;
ull p[maxn];
vector<int> G[maxn];
int a[maxn], sz[maxn], son[maxn], pos[maxn], cnt;
int id[maxn], rk[maxn], f[maxn], bot[maxn], n;
struct HASH {
ull c[maxn];
void up(int x, ull v) {
v *= p[x];
for (; x <= n; x += low(x))
c[x] += v;
}
ull qu(int x) {
ull res = 0;
for (; x; x -= low(x))
res += c[x];
return res;
}
ull query(int l, int r) {
ll res = qu(r) - qu(l - 1);
return res * p[n - l];
}
} T1, T2;
void dfs1(int u, int fa) {
sz[u] = 1;
f[u] = fa;
sort(G[u].begin(), G[u].end());
int i = 0;
for (auto v : G[u]) {
dfs1(v, u);
sz[u] += sz[v];
++i;
if (sz[son[u]] < sz[v])
son[u] = v, pos[u] = i;
}
}
void dfs2(int u, int top) {
id[u] = ++cnt;
rk[cnt] = u;
if (!son[u]) {
bot[u] = u;
T1.up(id[u], -9102);
return;
}
else {
dfs2(son[u], top);
bot[u] = bot[son[u]];
}
T1.up(id[u], pos[u]);
for (auto v : G[u])
if (v != son[u])
dfs2(v, v);
}
int lcp(int l1, int r1, int l2, int r2) {
int L = 0, R = min(r1 - l1 + 1, r2 - l2 + 1);
while (L < R) {
int m = (L + R) / 2;
if (T1.query(l1, l1 + m) != T2.query(l2, l2 + m))
R = m;
else
L = m + 1;
}
return L;
}
int gao(int x, int l, int r) {
int L = id[x], R = id[bot[x]];
while (l <= r) {
int k = lcp(L, R, l, r);
l += k;
int o = rk[L + k];
if (l > r || a[l] > G[o].size())
return o;
x = G[o][a[l] - 1];
l++;
if (l > r)
return x;
L = id[x];
R = id[bot[x]];
}
}
int main() {
p[0] = 1;
for (int i = 1; i < maxn; i++)
p[i] = p[i - 1] * base;
int m, q, l, r, opt, x, rt;
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
if (x)
G[x].push_back(i);
else
rt = i;
}
for (int i = 1; i <= m; i++) {
scanf("%d", &a[i]);
T2.up(i, a[i]);
}
dfs1(rt, 0);
dfs2(rt, rt);
while (q--) {
scanf("%d", &opt);
if (opt == 1) {
scanf("%d%d%d", &x, &l, &r);
printf("%d\n", gao(x, l, r));
}
else {
scanf("%d%d", &l, &x);
T2.up(l, x - a[l]);
a[l] = x;
}
}
}