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

Problem Description
As you know, Alice and Bob always play game together, and today they get a tree.

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?

 
Input
In the first line there is an integer T, indicating the number of test cases.

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
For each test case:

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.

 
Sample Input
1
3
1 2 3
1 2
2 3
3
1
2
3
 
Sample Output
Case #1: 2 1 -1
 
  1. 题意:
  2. 给出一颗树,每次有两人在某个子树进行博弈。
  3. 每次博弈两人轮流分别选取一个节点,得分为两者选取的节点的权值的xor值。
  4. 先手希望得分尽量大,后手希望得分尽量小,问每次博弈的最终得分。

  

  1. 题解:
  2. 显然对于一次询问,如果将某个子树的节点权值的01TRIE建出来,那么是可以查询出答案的。
  3. 考虑一颗已经建好的01权值Trie,每个节点都可以处理出在这个点向下进行题意所述的博弈的答案。
  4. 考虑这个节点某个孩子对这个节点的贡献.
  5. 若孩子的size>1,那么如果先手选择走这边(即选择的权值在这一个二进制位上是0或者1),另一个人也会走这边,那么用孩子的答案更新父亲。
  6. 若孩子的size1,那么只能暴力往另一边走,看看xor的最小值是什么,然后更新答案。
  7. 这个暴力的对于每个size1的孩子都要进行,每次代价是Ologn)的。
  8.  
  9. 那么考虑整棵树,如果孩子已经建好了,那么每次用启发式合并,将孩子合并起来。
  10. 每次插入一条链,对01Trie的影响可以用上述方法一次更新。
  11. 共需要Onlogn)次的插入。每次插入需要Ologn)的复杂度。
  12. 那么每次更新的复杂度:
  13. 如果子树大小>1,更新是O1)的,否则为Ologn)。
  14. 每次插入都有可能得到size == 1的孩子,共插入Onlogn),每次更新需要Ologn)的时间更新。
  15. 注意,每次插入,对于size==1的孩子,之后暴力一次,再往上显然就不需要暴力了。
  16. 因为能够暴力的前提是另一个孩子的size != 0,所以当前节点的size > 1
  17.  
  18. 总体复杂度Onlognlogn)。

  

  1. const int N = , M = , MAXBIT = ;
  2.  
  3. int n, m;
  4. int w[N];
  5. int ans[N];
  6.  
  7. struct AdjacencyList {
  8. int head[N], son[N * ], nex[N * ], tot;
  9.  
  10. inline void init(int n) {
  11. for(int i = ; i < n; ++i) head[i] = -;
  12. tot = ;
  13.  
  14. for(int i = ; i < n; ++i) visit[i] = false;
  15. }
  16.  
  17. inline void addEdge(int u, int v) {
  18. son[tot] = v, nex[tot] = head[u];
  19. head[u] = tot++;
  20. }
  21.  
  22. bool visit[N];
  23. inline void bfs(int st, int que[]) {
  24. int len = ;
  25. visit[que[len++] = st] = true;
  26. for(int idx = ; idx < len; idx++) {
  27. int u = que[idx];
  28. for(int tab = head[u], v; tab != -; tab = nex[tab])
  29. if(!visit[v = son[tab]])
  30. visit[v] = true, que[len++] = v;
  31. }
  32. }
  33. } edges;
  34.  
  35. struct Trie {
  36. static struct Node {
  37. static int tot;
  38.  
  39. int child[], size;
  40.  
  41. int f;
  42.  
  43. inline void init() {
  44. child[] = child[] = -, size = f = ;
  45. }
  46.  
  47. } tr[N * M * M];
  48.  
  49. #define child(x, y) tr[x].child[y]
  50. #define lch(x) child(x, 0)
  51. #define rch(x) child(x, 1)
  52. #define size(x) (x == -1 ? 0 : tr[x].size)
  53. #define f(x) tr[x].f
  54.  
  55. int rot;
  56.  
  57. inline int bruteForce(int u, int v, int d) {
  58. int ret = ;
  59. while(d >= ) {
  60. int t = size(lch(v)) == ;
  61. int _t = t;
  62. if(size(child(u, _t)) == ) _t ^= , ret += ( << d);
  63. u = child(u, _t), v = child(v, t), --d;
  64. }
  65. return ret;
  66. }
  67.  
  68. inline void updata(int u, int d) {
  69. f(u) = -;
  70. if(size(u) > ) {
  71. f(u) = ;
  72. for(int t = ; t < ; ++t) {
  73. int v = child(u, t);
  74. if(size(v) > ) f(u) = max(f(u), f(v));
  75. else if(size(v) == ) {
  76. int xorValue = bruteForce(child(u, t ^ ), v, d - );
  77. xorValue += ( << d);
  78. f(u) = max(f(u), xorValue);
  79. }
  80. }
  81. }
  82. }
  83.  
  84. inline void addVal(int &x, int val, int w, int d) {
  85. if(x == -) tr[x = Node::tot++].init();
  86. tr[x].size += w;
  87. if(d >= ) addVal(child(x, (val & ( << d)) > ), val, w, d - );
  88.  
  89. updata(x, d);
  90. }
  91.  
  92. inline void add(int val, int w) {
  93. addVal(rot, val, w, MAXBIT - );
  94. }
  95.  
  96. inline void traverse(int x, int now, int d, Trie &pro) {
  97. if(x == -) return;
  98. if(d < ) pro.add(now, size(x));
  99. else {
  100. if(size(lch(x)) > )
  101. traverse(lch(x), now, d - , pro);
  102. if(size(rch(x)) > )
  103. traverse(rch(x), now + ( << d), d - , pro);
  104. }
  105. }
  106.  
  107. inline void operator +=(Trie &t) {
  108. if(size(rot) < size(t.rot)) swap(rot, t.rot);
  109. t.traverse(t.rot, , MAXBIT - , *this);
  110. }
  111.  
  112. inline int getAnswer() const {
  113. return f(rot);
  114. }
  115.  
  116. } tr[N];
  117. int Trie::Node::tot;
  118. Trie::Node Trie::tr[N * M * M];
  119.  
  120. int bfsList[N];
  121.  
  122. inline void init() {
  123. edges.init(n);
  124. Trie::Node::tot = ;
  125. for(int i = ; i < n; ++i) tr[i].rot = -;
  126. }
  127.  
  128. inline void solve() {
  129. edges.bfs(, bfsList);
  130.  
  131. for(int i = n - ; i >= ; --i) {
  132. int u = bfsList[i];
  133. tr[u].add(w[u], );
  134. for(int tab = edges.head[u], v; tab != -; tab = edges.nex[tab])
  135. if(tr[v = edges.son[tab]].rot != -)
  136. tr[u] += tr[v];
  137. ans[u] = tr[u].getAnswer();
  138. }
  139.  
  140. scanf("%d", &m);
  141. while(m--) {
  142. int x;
  143. scanf("%d", &x);
  144. printf("%d\n", ans[x - ]);
  145. }
  146. }
  147.  
  148. int main() {
  149. int testCase;
  150. scanf("%d", &testCase);
  151. for(int testIndex = ; testIndex <= testCase; ++testIndex) {
  152. scanf("%d", &n);
  153. init();
  154. for(int i = ; i < n; ++i) scanf("%d", &w[i]);
  155. for(int i = , u, v; i < n; ++i) {
  156. scanf("%d%d", &u, &v);
  157. --u, --v;
  158. edges.addEdge(u, v), edges.addEdge(v, u);
  159. }
  160. printf("Case #%d:\n", testIndex);
  161. solve();
  162. }
  163. return ;
  164. }

2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 2016中国大学生程序设计竞赛 - 网络选拔赛 1004 Danganronpa

    Problem Description Chisa Yukizome works as a teacher in the school. She prepares many gifts, which ...

  4. 2016中国大学生程序设计竞赛 - 网络选拔赛 1011 Lweb and String

    Problem Description Lweb has a string S. Oneday, he decided to transform this string to a new sequen ...

  5. 2016中国大学生程序设计竞赛 - 网络选拔赛 1001 A water problem (大数取余)

    Problem Descripton Two planets named Haha and Xixi in the universe and they were created with the un ...

  6. 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  7. HDU 6150 - Vertex Cover | 2017 中国大学生程序设计竞赛 - 网络选拔赛

    思路来自 ICPCCamp /* HDU 6150 - Vertex Cover [ 构造 ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 题意: 给了你一个贪心法找最小覆盖的算法,构造一组 ...

  8. 2018中国大学生程序设计竞赛 - 网络选拔赛 1001 - Buy and Resell 【优先队列维护最小堆+贪心】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6438 Buy and Resell Time Limit: 2000/1000 MS (Java/O ...

  9. 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...

随机推荐

  1. java支持跨平台获取cpuid、主板id、硬盘id、mac地址 (兼容windows、Linux)

    windows: package cn.net.comsys.helper.system.info;   import java.io.BufferedReader; import java.io.F ...

  2. SQL case

    case when Value='1' then 'True'  else 'False' end as 'Result'

  3. 面试题目——《CC150》排序与查找

    面试题11.1:给定两个排序后的数组A和B,其中A的末端有足够的缓冲空间容纳B.编写一个方法,将B合并入A并排序. package cc150.sort_search; public class Me ...

  4. [Unity3D] Normal map、Diffuse map 和 Speculer map

    Normal map : Normal map (法线贴图) 它的作用是模拟出高模上的一些细节纹理,特别是将高模上的圆滑和粗糙度投射到低模上,让低模也有高模的效果. 因为高模的面数非常多,导入引擎后电 ...

  5. 获取APP最新版本的接口案例

    思路: 开发初期.安卓的应用可能没有上传到应用市场,可以把应用apk放到服务器上,供用户下载.把对应用的版本信息整理成为一个XML文件,放到服务器上,通过接口读取xml文件,获取有版本信息,然后安卓端 ...

  6. tyvj1198 最优矩阵连乘

    描述    一个n*m矩阵由n行m列共n*m个数排列而成.两个矩阵A和B可以相乘当且仅当A的列数等于B的行数.一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算量为nmp.   矩阵乘法满 ...

  7. NOIP2012同余方程

    描述 求关于 x的同余方程  ax ≡ 1(mod b) 的最小正整数解. 输入格式 输入文件 mod.in输入只有一行,包含两个正整数a,b,用一个空格隔开. 输出格式 输出文件 为 modmod  ...

  8. iOS开发UI中懒加载的使用方法

    1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其getter方法.说的通俗一点,就是在开发中,当程序中需要利用的资源时.在程序启动的时候不加载 ...

  9. java后端制作MD5加密

    由于一次业务的需要,我制作了一次密码的修改子业务. 当用户忘记密码的情况下,我需要动态的发给他一个6位的随机密码,通过即时通,短信,微信等.并同时修改数据库中的原密码为这6位的随机密码.让用户再去修改 ...

  10. am335x watchdog 设备出错

    问题描述: am335x watchdog 设备节点打开失败. 如果是直接将omap_wdt 直接编译成uImage,这样会出现打开文件节点失败的情况. 如果单独编译成模块在后面文件系统内插入则不会. ...