2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob
Alice and Bob
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 147 Accepted Submission(s): 22
The tree consists of n vertices, and vertex 1 is the root of this tree.
There is a number w[i] written on the ith vectex. Alice and Bob want to play a game on a subtree of this tree. (Note that there are only n subtrees, since the tree is rooted.)
Firstly Alice will choose a vertex in this subtree, and Bob must to choose a different vertex in this subtree. (So, Bob knows which vertex Alice chosen.)
At last they will get a result number equals the XOR sum of the number written on the two vertices which they chosen.
But the problem is that Alice wants the result number to be as maximal as possible while Bob wants the result number to be as minimal as possible, and of course they are clever enough.
Now we are interested in the result number, can you tell us?
For each test case:
The first line includes an integer n.
The second line includes n integers w[i], indicating the number written on the ith vertex.
For the next n−1 lines, each line includes two integers u and v, which means an edge in the tree.
The next line includes an integer m, which means the number of our queries.
The next m lines, each line includes an integer u, indicating Alice and Bob play game on the subtree rooted on the vertex u, and we want to know the result number.
1≤n,m≤100000,0≤w[i]≤100000.
Output “Case #k:”(without quotes) one line first, where k means the case number count from 1.
Then output m lines, each line must include the answer of the corresponding query. If Alice and Bob can’t choose two different vertices, output -1 instead.
3
1 2 3
1 2
2 3
3
1
2
3
题意:
给出一颗树,每次有两人在某个子树进行博弈。
每次博弈两人轮流分别选取一个节点,得分为两者选取的节点的权值的xor值。
先手希望得分尽量大,后手希望得分尽量小,问每次博弈的最终得分。
题解:
显然对于一次询问,如果将某个子树的节点权值的01TRIE建出来,那么是可以查询出答案的。
考虑一颗已经建好的01权值Trie,每个节点都可以处理出在这个点向下进行题意所述的博弈的答案。
考虑这个节点某个孩子对这个节点的贡献.
若孩子的size>1,那么如果先手选择走这边(即选择的权值在这一个二进制位上是0或者1),另一个人也会走这边,那么用孩子的答案更新父亲。
若孩子的size为1,那么只能暴力往另一边走,看看xor的最小值是什么,然后更新答案。
这个暴力的对于每个size为1的孩子都要进行,每次代价是O(logn)的。 那么考虑整棵树,如果孩子已经建好了,那么每次用启发式合并,将孩子合并起来。
每次插入一条链,对01Trie的影响可以用上述方法一次更新。
共需要O(nlogn)次的插入。每次插入需要O(logn)的复杂度。
那么每次更新的复杂度:
如果子树大小>1,更新是O(1)的,否则为O(logn)。
每次插入都有可能得到size == 1的孩子,共插入O(nlogn),每次更新需要O(logn)的时间更新。
注意,每次插入,对于size==1的孩子,之后暴力一次,再往上显然就不需要暴力了。
因为能够暴力的前提是另一个孩子的size != 0,所以当前节点的size > 1。 总体复杂度O(nlognlogn)。
const int N = , M = , MAXBIT = ; int n, m;
int w[N];
int ans[N]; struct AdjacencyList {
int head[N], son[N * ], nex[N * ], tot; inline void init(int n) {
for(int i = ; i < n; ++i) head[i] = -;
tot = ; for(int i = ; i < n; ++i) visit[i] = false;
} inline void addEdge(int u, int v) {
son[tot] = v, nex[tot] = head[u];
head[u] = tot++;
} bool visit[N];
inline void bfs(int st, int que[]) {
int len = ;
visit[que[len++] = st] = true;
for(int idx = ; idx < len; idx++) {
int u = que[idx];
for(int tab = head[u], v; tab != -; tab = nex[tab])
if(!visit[v = son[tab]])
visit[v] = true, que[len++] = v;
}
}
} edges; struct Trie {
static struct Node {
static int tot; int child[], size; int f; inline void init() {
child[] = child[] = -, size = f = ;
} } tr[N * M * M]; #define child(x, y) tr[x].child[y]
#define lch(x) child(x, 0)
#define rch(x) child(x, 1)
#define size(x) (x == -1 ? 0 : tr[x].size)
#define f(x) tr[x].f int rot; inline int bruteForce(int u, int v, int d) {
int ret = ;
while(d >= ) {
int t = size(lch(v)) == ;
int _t = t;
if(size(child(u, _t)) == ) _t ^= , ret += ( << d);
u = child(u, _t), v = child(v, t), --d;
}
return ret;
} inline void updata(int u, int d) {
f(u) = -;
if(size(u) > ) {
f(u) = ;
for(int t = ; t < ; ++t) {
int v = child(u, t);
if(size(v) > ) f(u) = max(f(u), f(v));
else if(size(v) == ) {
int xorValue = bruteForce(child(u, t ^ ), v, d - );
xorValue += ( << d);
f(u) = max(f(u), xorValue);
}
}
}
} inline void addVal(int &x, int val, int w, int d) {
if(x == -) tr[x = Node::tot++].init();
tr[x].size += w;
if(d >= ) addVal(child(x, (val & ( << d)) > ), val, w, d - ); updata(x, d);
} inline void add(int val, int w) {
addVal(rot, val, w, MAXBIT - );
} inline void traverse(int x, int now, int d, Trie &pro) {
if(x == -) return;
if(d < ) pro.add(now, size(x));
else {
if(size(lch(x)) > )
traverse(lch(x), now, d - , pro);
if(size(rch(x)) > )
traverse(rch(x), now + ( << d), d - , pro);
}
} inline void operator +=(Trie &t) {
if(size(rot) < size(t.rot)) swap(rot, t.rot);
t.traverse(t.rot, , MAXBIT - , *this);
} inline int getAnswer() const {
return f(rot);
} } tr[N];
int Trie::Node::tot;
Trie::Node Trie::tr[N * M * M]; int bfsList[N]; inline void init() {
edges.init(n);
Trie::Node::tot = ;
for(int i = ; i < n; ++i) tr[i].rot = -;
} inline void solve() {
edges.bfs(, bfsList); for(int i = n - ; i >= ; --i) {
int u = bfsList[i];
tr[u].add(w[u], );
for(int tab = edges.head[u], v; tab != -; tab = edges.nex[tab])
if(tr[v = edges.son[tab]].rot != -)
tr[u] += tr[v];
ans[u] = tr[u].getAnswer();
} scanf("%d", &m);
while(m--) {
int x;
scanf("%d", &x);
printf("%d\n", ans[x - ]);
}
} int main() {
int testCase;
scanf("%d", &testCase);
for(int testIndex = ; testIndex <= testCase; ++testIndex) {
scanf("%d", &n);
init();
for(int i = ; i < n; ++i) scanf("%d", &w[i]);
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
--u, --v;
edges.addEdge(u, v), edges.addEdge(v, u);
}
printf("Case #%d:\n", testIndex);
solve();
}
return ;
}
2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob的更多相关文章
- 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree
Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...
- 2016中国大学生程序设计竞赛 网络选拔赛 I This world need more Zhu
This world need more Zhu Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 1004 Danganronpa
Problem Description Chisa Yukizome works as a teacher in the school. She prepares many gifts, which ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 1011 Lweb and String
Problem Description Lweb has a string S. Oneday, he decided to transform this string to a new sequen ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 1001 A water problem (大数取余)
Problem Descripton Two planets named Haha and Xixi in the universe and they were created with the un ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】
Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- HDU 6150 - Vertex Cover | 2017 中国大学生程序设计竞赛 - 网络选拔赛
思路来自 ICPCCamp /* HDU 6150 - Vertex Cover [ 构造 ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 题意: 给了你一个贪心法找最小覆盖的算法,构造一组 ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1001 - Buy and Resell 【优先队列维护最小堆+贪心】
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6438 Buy and Resell Time Limit: 2000/1000 MS (Java/O ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...
随机推荐
- 如何将EXCEL表导入ORACLE数据库中?【转】
来源:https://zhidao.baidu.com/question/383828330.html?qbl=relate_question_2&word=excel%20%B1%ED%CA ...
- Zabbix3 agent端安装(二)
1.基础环境准备 安装zabbix的yum源,这里有必要提一点,阿里的yum源已经提供了zabbix3.0 1.1.yum源配置 rpm -ihv http://mirrors.aliyun.com/ ...
- Druid初步学习
Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系. DruidDataSource 高效可管理的数据库连接池 ...
- Asp.Net HttpContext.RemapHandler 用法
最近在看HttpHandler映射过程文章时发现Context对象中有一个RemapHandler方法,它能将当前请求映射到指定的HttpHandler处理,可跳过系统默认的Httphandler.它 ...
- print、sp_helptext的限制与扩展
在SQL中,使用动态SQL是很常见的.有些复杂的计算,或是存储过程,代码很长,中间可能有多次执行SQL语句.而调试拼串的SQL语句却是件痛苦的事,很难看出来运行的语句是什么.所以我会经常使用print ...
- nyoj 71 独木舟上的旅行(贪心专题)
独木舟上的旅行 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别.一条独木舟最多只能乘坐两个人,且乘客 ...
- [Hadoop] Hadoop学习笔记之Hadoop基础
1 Hadoop是什么? Google公司发表了两篇论文:一篇论文是“The Google File System”,介绍如何实现分布式地存储海量数据:另一篇论文是“Mapreduce:Simplif ...
- windows环境下面安装Apache2.4+MySql5.7+PHP5.6
之前学习PHP一致是只用phpStudy集成开发环境,这对于新手而言无疑是帮助极大的,因为傻瓜式安装与使用方法减少了我们很多不必要的麻烦.但是作为一名合格的PHP开发人员,掌握PHP+MySQL+Ap ...
- jQuery入门(3)事件与事件对象
jQuery入门(1)jQuery中万能的选择器 jQuery入门(2)使用jQuery操作元素的属性与样式 jQuery入门(3)事件与事件对象 jQuery入门(4)jQuery中的Ajax()应 ...
- Java多态与反射
多态通过分离做什么和怎么做,从另一个角度将接口与实现分离开来:通过多态来消除类型之间的耦合关系,在Java中,多态也叫动态绑定,后期绑定或运行时绑定,那么什么是方法绑定? 方法调用绑定: 将一个方法与 ...