题目链接

题目

题目描述

树国是一个有n个城市的国家,城市编号为1∼n。连接这些城市的道路网络形如一棵树,

即任意两个城市之间有恰好一条路径。城市中有k个帮派,编号为1∼k。每个帮派会占据一些城市,以进行非法交易。有时帮派之间会结盟,这就使得城市更加不安全了。同一座城市中可能有多个帮派。

当一些帮派结成联盟时,他们会更加强大,同时也更加危险。他们所控制的城市数会显著增加。具体地,一个联盟控制的城市是联盟中所有帮派所占据的城市,再加上这些城市两两之间路径上的所有城市。

shy是树国的市长,他想要选择一个城市作为首都。在决定之前,他要先做一些调研。为此,他找来你帮他回答一些询问,你能做到吗?在每个询问中,shy会选择一个城市作为首都,同时会告诉你当前活跃的帮派的集合。在这个询问中,你只需要考虑给定的集合中的帮派,其他的帮派你可以当作不存在。已知给定集合中的这些帮派结成了联盟,shy希望抓获联盟中的人,以得到关于整个联盟的一些信息。为此,他要找到被联盟控制的所有城市中离首都最近的一座城市到首都的距离。有可能首都本身就被控制了,此时答案为0。请注意,询问之间相互独立,互不影响。

输入描述

输入的第一行包含一个整数n,代表树国中的城市数。

接下来n−1行,每行包含两个整数u和v,代表城市u和v之间存在一条道路。

接下来一行包含一个整数k,代表树国中的帮派数。

接下来k行,每行描述一个帮派。第i行的第一个整数c[i]代表第i个帮派占据的城市数,接下来c[i]个整数,代表被第i个帮派占据的城市。

接下来一行包含一个整数Q,代表询问数。

接下来Q行,每行描述一个询问。每行的前两个整数V和t[i]代表本次询问中的首都与需要考虑的帮派集合的大小。接下来t[i]个整数代表本次询问中需要考虑的帮派。.

输出描述

对于每个询问,输出一行,包含一个整数,代表询问的答案。

示例1

输入

7
1 2
1 3
2 4
2 5
3 6
3 7
2
2 6 7
1 4
3
5 1 2
1 1 1
5 2 1 2

输出

2
1
1

备注

对于30%的数据,1≤n,k,Q≤1000, 1≤每个帮派占据城市数之和≤1000, 1≤每个询问中考虑的帮派数之和≤1000 对于60%的数据,1≤n,k,Q≤100000, 1≤每个帮派占据城市数之和≤100000, 1≤每个询问中考虑的帮派数之和≤100000 对于100%的数据,1≤n,k,Q≤500000, 1≤每个帮派占据城市数之和≤500000, 1≤每个询问中考虑的帮派数之和≤500000

题解

知识点:DFS序,LCA。

考虑一次询问的 \(t_i\) 个帮派的联盟,设它们城市的LCA为 \(lca\) 分类讨论:

  1. \(LCA(lca,x) \neq lca\) 时,说明 \(x\) 一定不会在这个联盟,答案是 \(dist(lca,x)\) 。
  2. \(LCA(lca,x) = lca\) 时,说明 \(x\) 在联盟LCA的子树里,可能会在被占据城市的路径上。此时,我们需要先得到离 \(x\) 最近的被占据城市 \(id\) ,计算 \(x\) 到 \(LCA(x,id)\) 的距离,即 \(x\) 到最近一条路径上的城市的距离。这是因为, \(LCA(x,id)\) 在 \(x\) 到 \(lca\) 的路径上,因此一定在某条占据城市的路径上,且这是距离 \(x\) 最近的一个城市。

其中,关于求出某个帮派最近的一个被占据的城市,记录帮派城市的dfn序列并排序,找出在排序后的序列里,离 \(x\) dfn序左右最近的两个城市即可,可以通过二分查找。

另外,我们可以事先求出每个帮派占据城市的LCA,在多次询问中可以节省时间。

时间复杂度 \(O(n\log n+\sum c_i + \sum t_i \log c_{q_i})\)

空间复杂度 \(O(n \log n + \sum c_i)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; struct Graph {
struct edge {
int v, nxt;
};
int idx;
vector<int> h;
vector<edge> e; Graph(int n = 0, int m = 0) { init(n, m); } void init(int n, int m) {
idx = 0;
h.assign(n + 1, 0);
e.assign(m + 1, {});
} void add(int u, int v) {
e[++idx] = { v,h[u] };
h[u] = idx;
}
}; template<class T>
struct ST {
vector<vector<T>> node; public:
ST() {}
ST(const vector<T> &src) { init(src); } void init(const vector<T> &src) {
assert(src.size());
int n = src.size() - 1;
int sz = log2(n);
node.assign(sz + 1, vector<T>(n + 1));
for (int i = 1;i <= n;i++) node[0][i] = src[i];
for (int i = 1;i <= sz;i++)
for (int j = 1;j + (1 << i) - 1 <= n;j++)
node[i][j] = node[i - 1][j] + node[i - 1][j + (1 << i - 1)];
} T query(int l, int r) {
int k = log2(r - l + 1);
return node[k][l] + node[k][r - (1 << k) + 1];
}
}; const int N = 500007;
Graph g; int dfncnt, eulcnt;
int dfn[N], pos[N], eul[N << 1], dep[N];//! euler序列要两倍
void dfs(int u, int fa) {
dfn[++dfncnt] = u;
eul[++eulcnt] = u;
pos[u] = eulcnt;
dep[u] = dep[fa] + 1;
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v;
if (fa == v) continue;
dfs(v, u);
eul[++eulcnt] = eul[pos[u]];
}
} struct T {
int mi;
friend T operator+(const T &a, const T &b) { return { dep[a.mi] < dep[b.mi] ? a.mi : b.mi }; }
}; ST<T> st;
int LCA(int u, int v) {
u = pos[u], v = pos[v];
if (u > v) swap(u, v);
return st.query(u, v).mi;
} int dis(int u, int v) { return dep[u] + dep[v] - 2 * dep[LCA(u, v)]; } int c[N];
int c_lca[N];
vector<int> c_id[N];
int Q[N]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
g.init(n, n << 1);
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g.add(u, v);
g.add(v, u);
} dfs(1, 0);
vector<T> eul_src(eulcnt + 1);
for (int i = 1;i <= eulcnt;i++) eul_src[i] = { eul[i] };
st.init(eul_src); auto f = [&](int a, int b) {return pos[a] < pos[b];}; int k;
cin >> k;
for (int i = 1;i <= k;i++) {
cin >> c[i];
for (int j = 1;j <= c[i];j++) {
int x;
cin >> x;
c_id[i].push_back(x);
c_lca[i] = j == 1 ? x : LCA(c_lca[i], x);
}
sort(c_id[i].begin(), c_id[i].end(), f);
} int q;
cin >> q;
while (q--) {
int x, t;
cin >> x >> t;
int lca;
for (int i = 1;i <= t;i++) {
cin >> Q[i];
lca = i == 1 ? c_lca[Q[i]] : LCA(lca, c_lca[Q[i]]);
}
if (LCA(x, lca) != lca) cout << dis(x, lca) << '\n';
else {
int ans = 1e9;
for (int i = 1;i <= t;i++) {
int id = lower_bound(c_id[Q[i]].begin(), c_id[Q[i]].end(), x, f) - c_id[Q[i]].begin();
if (id < c_id[Q[i]].size())ans = min(ans, dis(x, LCA(x, c_id[Q[i]][id])));
if (id > 0) ans = min(ans, dis(x, LCA(x, c_id[Q[i]][id - 1])));
}
cout << ans << '\n';
}
}
return 0;
}

NC13950 Alliances的更多相关文章

  1. Wannafly模拟赛2 C alliances(dfs序+二分)

    题目 https://www.nowcoder.com/acm/contest/4/C 题意 由n个点组成一个树,有m个帮派,每个帮派由一些个点组成,这些点以及它们两两路径上的所有点都属于该帮派的管辖 ...

  2. Alliances

    树国是一个有n个城市的国家,城市编号为1∼n.连接这些城市的道路网络形如一棵树, 即任意两个城市之间有恰好一条路径.城市中有k个帮派,编号为1∼k.每个帮派会占据一些城市,以进行非法交易.有时帮派之间 ...

  3. 牛客 4C Alliances (dfs序)

    大意: 给定树, 有$k$个帮派, 第$i$个帮派所占据点为$c_i$, 以及$c_i$两两相连路径上的所有点. 一个点可能被多个帮派占领. $q$个询问, 第$i$个询问给定$t_i$个帮派, 给定 ...

  4. #英文#品读中国城市个性——最好的和最坏的&当东方遇到西方

    冒险家的乐园 a playground of risk 实现发财梦 realize one's dreams of wealth 道德沦丧,堕落 moral deprivation 租界 foreig ...

  5. 魔兽争霸3 replay 格式

    ******************************************************************************* * WarCraft III Repla ...

  6. The Sorrows of Young Werther

    The Sorrows of Young Werther J.W. von Goethe Thomas Carlyle and R.D. Boylan Edited by Nathen Haskell ...

  7. Python统计词频的几种方式

    语料 text = """My fellow citizens: I stand here today humbled by the task before us, gr ...

  8. List of regional organizations by population

    https://baike.baidu.com/item/国际组织/261053?fr=aladdin 经济文化类组织(非政府组织) 创行 狮子会 全球青年领导力联盟 乐施会 政治类组织 欧洲联盟(欧 ...

  9. 奥巴马(Obama)获胜演讲全文[中英对照]+高清视频下载

    http://www.amznz.com/obama-speech/如果还有人对美国是否凡事都有可能存疑,还有人怀疑美国奠基者的梦想在我们所处的时代是否依然鲜活,还有人质疑我们的民主制度的力量,那么今 ...

  10. Distributed Management Task Force----分布式管理任务组

    http://baike.baidu.com/link?url=Y9HGLs8Qj6pXbbgY6xPdfiGDsQO8Eu1e80B4giQtQ_hAfGNF59byxnLoERYri4Duw7Gw ...

随机推荐

  1. docker 原理之 user namespace(下)

    1. user namespace user namespace 主要隔离了安全相关的标识符和属性,包括用户 ID,用户组 ID,key 和 capabilities 等.同样一个用户 id 在不同 ...

  2. jenkins构建报错: Send build artifacts over SSH' changed build result to UNSTABLE

    原因包括: ssh配置的用户没有相关的权限. 最好是配置root用户

  3. [转帖]“炫技” 还是 “真硬核”,OpenPPL 实测阿里「倚天 710」芯片

    https://my.oschina.net/openppl/blog/5524424   本文将以深度学习模型推理应用为出发点,对「倚天 710」这款 ARM Server 芯片进行性能方面的实测. ...

  4. [转帖]oracle通过pid查找执行SQL

    通过TOP 命令查看PID:1560 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1560 oracle 20 0 38.978g 0. ...

  5. [转帖]TiDB-merge region相关问题

    一.开启region merge # 控制 Region Merge 的 size 上限,当 Region Size 大于指定值时 PD 不会将其与相邻的 Region 合并 pd-ctl confi ...

  6. [转帖]elasticsearch-create-enrollment-tokenedit

    https://www.elastic.co/guide/en/elasticsearch/reference/current/create-enrollment-token.html The ela ...

  7. [转帖]Kafka高可用 — KRaft集群搭建

    Apache Kafka Raft 是一种共识协议,它的引入是为了消除 Kafka 对 ZooKeeper 的元数据管理的依赖,被社区称之为 Kafka Raft metadata mode,简称 K ...

  8. [转帖]【mmap】深度分析mmap:是什么 为什么 怎么用 性能总结

    https://blog.csdn.net/bandaoyu/article/details/106750990 目录 有什么用? 1.文件映射 2.分配内存(匿名文件映射) mmap基础概念 mma ...

  9. [转帖]SystemStap、BCC、bpftrace

    https://plantegg.github.io/2019/09/16/SystemStap/ Linux 4.4+ 支持 eBPF.基于 eBPF 可以将任何内核函数调用转换成可带任何 数据的用 ...

  10. fio test 简单查看一些系统的io性能结果

    简单测试的脚本: echo "本次测试测试128k 16k 8k 1k 的 顺序读写 随机读写性能,每个脚本耗时约30s, 总计耗时大约8min左右完成: " fio -name= ...