登录—专业IT笔试面试备考平台_牛客网
题意:
思路:
这种是典中典中典,对于gcd,背包问题都是一样的处理方式
预处理出前缀lca和后缀lca,枚举哪个消失即可,可以统计方案数
Code:
#include <bits/stdc++.h>
constexpr int N = 2e5 + 10;
constexpr int mod = 1e9 + 7;
constexpr int Inf = 0x3f3f3f3f;
constexpr double eps = 1e-10;
std::vector<int> adja[N], adjb[N];
int n, k;
int x[N];
int a[N], b[N];
int pa[N], pb[N];
int depa[N], depb[N];
int Fa[N][33], Fb[N][33];
int prea[N], sufa[N], preb[N], sufb[N];
void dfs1(int u, int fa) {
depa[u] = depa[fa] + 1;
Fa[u][0] = fa;
for (int j = 1; j <= 30; j ++) Fa[u][j] = Fa[Fa[u][j - 1]][j - 1];
for (auto v : adja[u]) {
if (v == fa) continue;
dfs1(v, u);
}
}
void dfs2(int u, int fa) {
depb[u] = depb[fa] + 1;
Fb[u][0] = fa;
for (int j = 1; j <= 30; j ++) Fb[u][j] = Fb[Fb[u][j - 1]][j - 1];
for (auto v : adjb[u]) {
if (v == fa) continue;
dfs2(v, u);
}
}
int lca_a(int u, int v) {
if (depa[u] < depa[v]) std::swap(u, v);
for (int j = 30; j >= 0; j --) {
if (depa[Fa[u][j]] >= depa[v]) {
u = Fa[u][j];
}
}
if (u == v) return u;
for (int j = 30; j >= 0; j --) {
if (Fa[u][j] != Fa[v][j]) {
u = Fa[u][j];
v = Fa[v][j];
}
}
return Fa[u][0];
}
int lca_b(int u, int v) {
if (depb[u] < depb[v]) std::swap(u, v);
for (int j = 30; j >= 0; j --) {
if (depb[Fb[u][j]] >= depb[v]) {
u = Fb[u][j];
}
}
if (u == v) return u;
for (int j = 30; j >= 0; j --) {
if (Fb[u][j] != Fb[v][j]) {
u = Fb[u][j];
v = Fb[v][j];
}
}
return Fb[u][0];
}
void solve() {
std::cin >> n >> k;
for (int i = 1; i <= k; i ++) std::cin >> x[i];
for (int i = 1; i <= n; i ++) {
std::cin >> a[i];
}
for (int i = 2; i <= n; i ++) {
std::cin >> pa[i];
adja[pa[i]].push_back(i);
adja[i].push_back(pa[i]);
}
for (int i = 1; i <= n; i ++) {
std::cin >> b[i];
}
for (int i = 2; i <= n; i ++) {
std::cin >> pb[i];
adjb[pb[i]].push_back(i);
adjb[i].push_back(pb[i]);
}
dfs1(1, 0);
dfs2(1, 0);
prea[1] = x[1];
for (int i = 2; i <= k; i ++) {
prea[i] = lca_a(prea[i - 1], x[i]);
}
preb[1] = x[1];
for (int i = 2; i <= k; i ++) {
preb[i] = lca_b(preb[i - 1], x[i]);
}
sufa[k] = x[k];
for (int i = k - 1; i >= 1; i --) {
sufa[i] = lca_a(sufa[i + 1], x[i]);
}
sufb[k] = x[k];
for (int i = k - 1; i >= 1; i --) {
sufb[i] = lca_b(sufb[i + 1], x[i]);
}
int ans = 0;
int cur1 = sufa[2];
int cur2 = sufb[2];
if (a[cur1] > b[cur2]) ans ++;
for (int i = 2; i <= k - 1; i ++) {
int cur1 = lca_a(prea[i - 1], sufa[i + 1]);
int cur2 = lca_b(preb[i - 1], sufb[i + 1]);
if (a[cur1] > b[cur2]) ans ++;
};
cur1 = prea[k - 1];
cur2 = preb[k - 1];
if (a[cur1] > b[cur2]) ans ++;
std::cout << ans << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
while(t --) {
solve();
}
return 0;
}