简单数据结构题(from 钟子谦——IOI2018集训队自选题)

试题描述

给一棵 \(n\) 个点的树,点权开始为 \(0\) ,有 \(q\) 次操作,每次操作是选择一个点,把周围一圈点点权 \(+1\)(一个点周围的点为与该点距离为 \(1\) 的点),在该操作后你需要输出当前周围一圈点点权的异或和。

由于输出量较大,设第 \(i\) 个询问输出为 \(ans_i\),你只需要输出

\begin{equation}

[\sum^q_{i=1}ans_i \cdot (i^2+i)] \texttt{ mod } (10^9+7)

\notag

\end{equation}

输入

第一行两个数 \(n\) , \(q\) ,表示树的点数和操作数。

接下来 \(n-1\) 行每行两个数表示树上的一条边。

接下来 \(q\) 行每行一个数 \(x\),表示把 \(x\) 周围一圈点点权 \(+1\)。

输出

输出一个 \([0,10^9+7)\) 的数,详见题目描述。

输入示例

  1. 5 10
  2. 1 2
  3. 2 3
  4. 2 4
  5. 3 5
  6. 1
  7. 5
  8. 2
  9. 4
  10. 3
  11. 5
  12. 4
  13. 2
  14. 3
  15. 1

输出示例

  1. 2060

数据规模及约定

对于 \(80\texttt{%}\) 的数据,保证 \(n = 1000\)

对于 \(90\texttt{%}\) 的数据,保证 \(n = 100000\)

对于 \(100\texttt{%}\) 的数据,保证 \(n = 500000\)

题解

这题差最后一步想到了。

不过好像除了 trie 树这步最妙这题也没其他什么了。。。

每个点周围的点可以分为父节点和子树中的一层节点,所以我们可以把一个节点 \(u\) 的所有儿子的信息存储到节点 \(u\) 中,然后对于一个询问,父亲单独计算,统一计算所有儿子的。

所以现在要一个可以支持删除、插入(对父亲的单独操作)、全体加 \(1\)、求全体异或和的数据结构。

一个数 \(x\) 加上 \(1\) 可以看做 \(x \rightarrow x \bigoplus (2 \cdot lowbit(\texttt{~}x) - 1)\)(\(\bigoplus\) 表示异或运算符,\(\texttt{~}\) 表示取反运算符,\(lowbit(t)\) 表示只取 \(t\) 最低位的 \(1\)),所以我们需要维护集合内所有 \(x\) 的同时维护所有的 \(lowbit(\texttt{~}x)\),确切地,只需要知道每种 \(lowbit(x)\)(最多 \(\log q\) 种)的取值有多少个。

然后就是我没想到的最后一步了:建立 trie 树保存集合内所有数(从浅到深按从低位到高位的顺序保存),\(lowbit(\texttt{~}x)\) 很好得到了,然后全体 \(+1\) 就是每次交换左右子树,然后递归到左子树去(即最低位异或 \(1\) 然后处理进位)。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cctype>
  6. #include <algorithm>
  7. using namespace std;
  8. #define rep(i, s, t) for(int i = (s); i <= (t); i++)
  9. #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
  10. int read() {
  11. int x = 0, f = 1; char c = getchar();
  12. while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
  13. while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
  14. return x * f;
  15. }
  16. #define maxn 500010
  17. #define maxm 1000010
  18. #define maxnode 10000010
  19. #define maxlog 25
  20. #define MOD 1000000007
  21. #define LL long long
  22. int n, m, head[maxn], nxt[maxm], to[maxm], Fa[maxn], at[maxn];
  23. int ToT, rt[maxn], val[maxnode], ch[maxnode][2], siz[maxnode], fa[maxnode], rec[maxlog], cntr;
  24. void AddEdge(int a, int b) {
  25. to[++m] = b; nxt[m] = head[a]; head[a] = m;
  26. swap(a, b);
  27. to[++m] = b; nxt[m] = head[a]; head[a] = m;
  28. return ;
  29. }
  30. int getnode() {
  31. int u;
  32. if(cntr) u = rec[cntr--];
  33. else u = ++ToT;
  34. ch[u][0] = ch[u][1] = fa[u] = siz[u] = 0;
  35. return u;
  36. }
  37. int Insert(int& r, int v) {
  38. if(!r) r = getnode(), val[r] = v;
  39. else val[r] ^= v;
  40. int u = r; siz[u]++;
  41. rep(i, 1, 20) {
  42. int x = v & 1; v >>= 1;
  43. if(!ch[u][x]) fa[ch[u][x] = getnode()] = u;
  44. u = ch[u][x]; siz[u]++;
  45. }
  46. // printf("Insert(%d): %d\n", r, u);
  47. return u;
  48. }
  49. void build(int u) {
  50. rt[u] = ++ToT;
  51. for(int e = head[u]; e; e = nxt[e]) if(to[e] != Fa[u]) {
  52. at[to[e]] = Insert(rt[u], 0);
  53. Fa[to[e]] = u;
  54. build(to[e]);
  55. }
  56. return ;
  57. }
  58. int getnum(int u) {
  59. int res = 0; cntr = 0;
  60. while(u) {
  61. if(fa[u] && ch[fa[u]][1] == u) res = res << 1 | 1;
  62. else if(fa[u]) res <<= 1;
  63. // printf("getnum: %d\n", u);
  64. siz[u]--;
  65. if(!siz[u] && fa[u]) {
  66. rec[++cntr] = u;
  67. // printf("recycle %d\n", u);
  68. if(ch[fa[u]][1] == u) ch[fa[u]][1] = 0;
  69. else ch[fa[u]][0] = 0;
  70. }
  71. if(!fa[u]) val[u] ^= res;
  72. u = fa[u];
  73. }
  74. return res;
  75. }
  76. void Add(int r) {
  77. int u = r, d = 0;
  78. while(u) {
  79. int s = ch[u][0] ? siz[ch[u][0]] : 0;
  80. if(!ch[u][1]) s = siz[u];
  81. if(s & 1) val[r] ^= (1 << d + 1) - 1;
  82. u = ch[u][1]; d++;
  83. }
  84. u = r;
  85. while(u) {
  86. swap(ch[u][0], ch[u][1]);
  87. u = ch[u][0];
  88. }
  89. return ;
  90. }
  91. int main() {
  92. n = read(); int q = read();
  93. rep(i, 1, n - 1) {
  94. int a = read(), b = read();
  95. AddEdge(a, b);
  96. }
  97. Insert(rt[0], 0);
  98. build(1);
  99. int Ans = 0;
  100. rep(i, 1, q) {
  101. int u = read(), ans = 0;
  102. if(Fa[u]) {
  103. ans = getnum(at[Fa[u]]) + 1;
  104. // printf("faans: %d\n", ans);
  105. at[Fa[u]] = Insert(rt[Fa[Fa[u]]], ans);
  106. }
  107. // printf("beforeAdd: %d\n", val[rt[u]]);
  108. Add(rt[u]);
  109. ans ^= val[rt[u]];
  110. // printf("afterAdd: %d\n", val[rt[u]]);
  111. (Ans += (LL)ans * ((LL)i * i % MOD + i) % MOD) %= MOD;
  112. }
  113. printf("%d\n", Ans);
  114. return 0;
  115. }

简单数据结构题(from 钟子谦——IOI2018集训队自选题)的更多相关文章

  1. test20191210 钟子谦

    100+40+0=140.暴力没写满-- 简单模拟 很久很久以前,有一个 \(1\sim n\) 的排列 \(a\),还有一个长度为 \(q\) 的,每个元素在 \(1\) 到 \(n\) 之间的序列 ...

  2. [Contest20171102]简单数据结构题

    给一棵$n$个点的数,点权开始为$0$,有$q$次操作,每次操作选择一个点,把周围一圈点点权$+1$,在该操作后你需要输出当前周围一圈点点权的异或和. 由于输出量较大,设第$i$个询问输出为$ans_ ...

  3. ioi2018集训队自选题:最短路练习题

    题意:链接 定义pos[i]表示i这个值在数组里的下标. 我们先用单调栈找到每个元素左边和右边第一个比它大的元素$l_i$和$r_i$,然后建一棵二叉树,我们就叫做maxtree吧 (upd:mdzz ...

  4. QDUOJ 一道简单的数据结构题 栈的使用(括号配对)

    一道简单的数据结构题 发布时间: 2017年6月3日 18:46   最后更新: 2017年6月3日 18:51   时间限制: 1000ms   内存限制: 128M 描述 如果插入“+”和“1”到 ...

  5. [LOJ#2326]「清华集训 2017」简单数据结构

    [LOJ#2326]「清华集训 2017」简单数据结构 试题描述 参加完IOI2018之后就是姚班面试.而你,由于讨厌物理.并且想成为乔布斯一样的创业家,被成功踢回贵系. 转眼,时间的指针被指向201 ...

  6. 2019浙大校赛--A--Thanks, TuSimple!(简单模拟题)

    这题前三段都是一堆吹爆赞助商的屁话,正式题目在图片下边,一个简单模拟题. 题目大意: 有n个男生,m个女生在进行舞会,其中一部分男生祥和比自己矮的女生跳舞,一部分男生想和比自己高的女生跳舞,一部分女生 ...

  7. 【Luogu3676】小清新数据结构题(动态点分治)

    [Luogu3676]小清新数据结构题(动态点分治) 题面 洛谷 题解 先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护. 做法大概是这样: 我们先以任意一个点为根,把当前点看成是一棵有根 ...

  8. python学习总结----简单数据结构

    mini-web服务器 - 能够完成简单的请求处理 - 使用http协议 - 目的:加深对网络编程的认识.为后面阶段学习web做铺垫 简单数据结构 - 排列组合 import itertools # ...

  9. 牛客练习赛22-E.简单数据结构1(扩展欧拉定理降幂 +树状数组)

    链接:E.简单数据结构1 题意: 给一个长为n的序列,m次操作,每次操作: 1.区间加 2.对于区间,查询 ,一直到- 请注意每次的模数不同.   题解:扩展欧拉定理降幂 对一个数p取log(p)次的 ...

随机推荐

  1. 使用pip 提示UnicodeDecodeError: 'ascii' codec can't decode解决方法

    python目录 Python27\Lib\site-packages 建一个文件sitecustomize.py 内容写: import sys sys.setdefaultencoding('gb ...

  2. 对象 -----JavaScript

    本文摘要:http://www.liaoxuefeng.com/ JavaScript的对象是一种无序的集合数据类型,它由若干键值对组成. JavaScript的对象用于描述现实世界中的某个对象.例如 ...

  3. React后台管理系统-商品管理列表组件

    1.商品列表页面结构 <div id="page-wrapper">              <PageTitle title="商品列表" ...

  4. 关于java中异常机制

    什么是异常:异常就是程序在运行时出现的不正常情况.对于严重的情况Java通过Error类进行描述,一般不用编写代码处理:对于不严重的情况Java通过Exception描述,一般编写针对性代码对其进行处 ...

  5. Log错误日志级别

    日志记录器(Logger)的级别顺序:     分为OFF.FATAL.ERROR.WARN.INFO.DEBUG.ALL或者您定义的级别.Log4j建议只使用四个级别,优先级 从高到低分别是 ERR ...

  6. linux普通文件权限和系统目录权限的实践及结论

    测试结论:linux普通文件的读.写.执行权限说明 1.可读r:表示具有读取\阅读文件内容的权限 2.可写w:表示具有新增.修改文件内容的权限 1)如果没有r配合,那么vi编辑文件会提示无法编辑(但可 ...

  7. JZOJ 1266. 玉米田

    1266. 玉米田(cowfood.pas/c/cpp) (File IO): input:cowfood.in output:cowfood.out Time Limits: 1000 ms  Me ...

  8. JVM 内存分配和回收策略

    对象的内存分配,主要是在java堆上分配(有可能经过JIT编译后被拆为标量类型并间接地在栈上分配),如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配.少数情况下也是直接分配到老年代,分配规则不 ...

  9. North American Invitational Programming Contest (NAIPC) 2016

    (待补) A. Fancy Antiques 爆搜. B. Alternative Bracket Notation C. Greetings! D. Programming Team 0/1分数规划 ...

  10. 扩展程序 - Google Chrome

    Adblock Plus 3.0.3 Adblock Plus 已被超过 1 亿台设备使用,是世界上最受欢迎的广告拦截软件. ID:cfhdojbkjhnklbpkdaibdccddilifddb 查 ...