题目链接

题目

题目描述

树国是一个有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. 使用XStream,XMLSerializer 解析及格式转换

    博主原创,转载请注明出处 1.引入对应的maven依赖: <!--xstream--> <dependency> <groupId>com.thoughtworks ...

  2. 部署开源项目管理工具focalboard

    前言 focalboard是一款开源项目管理工具,类似Jira.Trello.官网地址 组件 版本 说明 Debian 12.1 操作系统 docker 20.10.7 容器运行时 docker-co ...

  3. [转帖]实践真知:解决 Jdbc 连接 Oracle 12c 时快时慢的问题

    https://cloud.tencent.com/developer/article/1052506 李真旭@killdb Oracle ACE,云和恩墨技术专家 个人博客:www.killdb.c ...

  4. [转帖]SQL Server 2008~2022版本序列号/密钥/激活码 汇总

    https://www.cnblogs.com/cqpanda/p/16148822.html SQL Server 2022# Enterprise: J4V48-P8MM4-9N3J9-HD97X ...

  5. [转帖]Oracle、SQL Server、MySQL数据类型对比

    Oracle.SQL Server.MySQL数据类型对比 - 知乎 (zhihu.com) 1,标准SQL数据类型 BINARY 每个字符占一个字节 任何类型的数据都可存储在这种类型的字段中.不需数 ...

  6. 【转帖】io_uring vs epoll ,谁在网络编程领域更胜一筹?

    io_uring vs epoll ,谁在网络编程领域更胜一筹? 2021-12-16 1473举报 简介: 从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗 ...

  7. [转帖]Centos 7 查看磁盘io ,找出占用io读写很高的进程

    1,先用iostat查看磁盘io 是否读写负载很高 用iostat -x 1 10 如果 iostat 没有,要 yum install sysstat安装这个包,第一眼看下图红色圈圈的那个如果%ut ...

  8. [转帖]linux时间戳转换成时间指令_时间戳转换公式

    原文地址:http://wanping.blogbus.com/logs/28663569.html 1.时间戳转换为正常显示的时间格式 Freebsd 系统下: 转换命令为: date -r 111 ...

  9. [转帖]Windows磁盘性能压测(2)-Fio

    http://www.manongjc.com/detail/59-qftscgqzitmxpaw.html 目录 一.腾讯云官网硬盘性能指标 二.使用fio测试硬盘性能指标 1. 测试工具相关 2. ...

  10. [转帖] Linux命令拾遗-软件资源观测

    https://www.cnblogs.com/codelogs/p/16060443.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 这是Linux ...