简单数据结构题(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)\) 的数,详见题目描述。

输入示例

5 10
1 2
2 3
2 4
3 5
1
5
2
4
3
5
4
2
3
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\) 然后处理进位)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--)int read() {int x = 0, f = 1; char c = getchar();while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }return x * f;
}#define maxn 500010
#define maxm 1000010
#define maxnode 10000010
#define maxlog 25
#define MOD 1000000007
#define LL long longint n, m, head[maxn], nxt[maxm], to[maxm], Fa[maxn], at[maxn];
int ToT, rt[maxn], val[maxnode], ch[maxnode][2], siz[maxnode], fa[maxnode], rec[maxlog], cntr;void AddEdge(int a, int b) {to[++m] = b; nxt[m] = head[a]; head[a] = m;swap(a, b);to[++m] = b; nxt[m] = head[a]; head[a] = m;return ;
}int getnode() {int u;if(cntr) u = rec[cntr--];else u = ++ToT;ch[u][0] = ch[u][1] = fa[u] = siz[u] = 0;return u;
}
int Insert(int& r, int v) {if(!r) r = getnode(), val[r] = v;else val[r] ^= v;int u = r; siz[u]++;rep(i, 1, 20) {int x = v & 1; v >>= 1;if(!ch[u][x]) fa[ch[u][x] = getnode()] = u;u = ch[u][x]; siz[u]++;}
//  printf("Insert(%d): %d\n", r, u);return u;
}void build(int u) {rt[u] = ++ToT;for(int e = head[u]; e; e = nxt[e]) if(to[e] != Fa[u]) {at[to[e]] = Insert(rt[u], 0);Fa[to[e]] = u;build(to[e]);}return ;
}int getnum(int u) {int res = 0; cntr = 0;while(u) {if(fa[u] && ch[fa[u]][1] == u) res = res << 1 | 1;else if(fa[u]) res <<= 1;
//      printf("getnum: %d\n", u);siz[u]--;if(!siz[u] && fa[u]) {rec[++cntr] = u;
//          printf("recycle %d\n", u);if(ch[fa[u]][1] == u) ch[fa[u]][1] = 0;else ch[fa[u]][0] = 0;}if(!fa[u]) val[u] ^= res;u = fa[u];}return res;
}
void Add(int r) {int u = r, d = 0;while(u) {int s = ch[u][0] ? siz[ch[u][0]] : 0;if(!ch[u][1]) s = siz[u];if(s & 1) val[r] ^= (1 << d + 1) - 1;u = ch[u][1]; d++;}u = r;while(u) {swap(ch[u][0], ch[u][1]);u = ch[u][0];}return ;
}int main() {n = read(); int q = read();rep(i, 1, n - 1) {int a = read(), b = read();AddEdge(a, b);}Insert(rt[0], 0);build(1);int Ans = 0;rep(i, 1, q) {int u = read(), ans = 0;if(Fa[u]) {ans = getnum(at[Fa[u]]) + 1;
//          printf("faans: %d\n", ans);at[Fa[u]] = Insert(rt[Fa[Fa[u]]], ans);}
//      printf("beforeAdd: %d\n", val[rt[u]]);Add(rt[u]);ans ^= val[rt[u]];
//      printf("afterAdd: %d\n", val[rt[u]]);(Ans += (LL)ans * ((LL)i * i % MOD + i) % MOD) %= MOD;}printf("%d\n", Ans);return 0;
}

转载于:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7834859.html

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

  1. 福州三中 计算机竞赛,重磅快讯 | 刚刚,信息学奥赛世界金牌得主钟子谦凯旋!...

    原标题:重磅快讯 | 刚刚,信息学奥赛世界金牌得主钟子谦凯旋! 海峡教育报记者 罗菊熙 姚兴榕 文/图 8月12日晚 国际信息学奥林匹克竞赛 世界金牌得主钟子谦 载誉归来! 当天 清华大学招生办发来贺 ...

  2. 福州三中计算机培训班,麻省理工全奖录取 福州三中学霸钟子谦,揭秘学霸是如何炼成的!...

    在名师指点之下,钟子谦一发不可收拾,多次获得全国信息学联赛提高组一等奖,2017年和2018年连续两年均获信息学全国冬令营金牌.全国精英赛金牌.亚太地区竞赛金牌.全国信息学竞赛金牌.今年5月他入选信息 ...

  3. 简单的数据结构题(多项式、拉格朗日插值、线段树)

    简单的数据结构题 首先考虑计算要求的式子,不妨设l=1,r=nl=1,r=nl=1,r=n. ∑i=1naik∏j≠i1−aiajai−aj\sum_{i=1}^{n}a_i^k\prod_{j\n ...

  4. qduoj 一道简单的数据结构题(水题)

    题目链接:https://qduoj.com/problem/147/点击打开链接 一道简单的数据结构题 发布时间: 2017年6月3日 18:46   最后更新: 2017年6月3日 18:51   ...

  5. JAVA 判断简单密码算法_十道简单算法题二【Java实现】

    前言 清明不小心就拖了两天没更了-- 这是十道算法题的第二篇了-上一篇回顾:十道简单算法题 最近在回顾以前使用C写过的数据结构和算法的东西,发现自己的算法和数据结构是真的薄弱,现在用Java改写一下, ...

  6. 怎么获取codeforces的数据_原创 | codeforces 1417C,逆向思考的数据结构题

    点击上方蓝字,关注并星标,和我一起学技术. 大家好,欢迎阅读周末算法题专题. 今天我们选择的是codeforces contest 1417的C题k-Amazing Numbers.这是一道经典的数据 ...

  7. 数据结构题(莫队算法)

    数据结构题 题目: 问在区间[l,r]和[l1,r1]内x的出现次数的乘积是多少? 题解: 莫队算法的模板题 关于莫队算法你可以参考这个 我这里简单的说说我对莫队的理解: 莫队是一个优雅的暴力,就是将 ...

  8. java的简单算法题_[2]十道算法题【Java实现】

    前言 清明不小心就拖了两天没更了-- 这是十道算法题的第二篇了-上一篇回顾:十道简单算法题 最近在回顾以前使用C写过的数据结构和算法的东西,发现自己的算法和数据结构是真的薄弱,现在用Java改写一下, ...

  9. 学习笔记之15道简单算法题

    15道简单算法题 http://www.cnblogs.com/hlxs/archive/2014/06/06/3772333.html (●-●) | 剑指Offer_编程题_牛客网 http:// ...

最新文章

  1. 软件测试技术篇:UI自动化到底是难是易?
  2. 29.进程和线程的区别
  3. Oracle SQL中实现indexOf和lastIndexOf功能
  4. LeetCode 346. 数据流中的移动平均值(队列)
  5. python的selenium模块_Python中Selenium模块的使用
  6. Windows平台Unity3d下如何同时播放多路RTSP或RTMP流
  7. HTML+CSS+JS实现 ❤️经典霓虹灯英文字母特效❤️
  8. javascript 总结(常用工具类的封装)(转)
  9. Windows平台下sbt的安装设置
  10. 面向java开发者的函数式编程_函数式编程让你忘记设计模式
  11. realme X7 Pro至尊版确认:最便宜的曲面屏手机
  12. ABP官方文档翻译 1.2 N层架构
  13. Binder框架在Framework层的C++中的使用
  14. Visual Studio(VS2017/VS2019) C++ 配置 CPLEX 教程
  15. matlab曼德勃罗集,YaK与您一起欣赏BBC纪录片:''''神秘的混沌理论''''
  16. Qt - 获取屏幕分辨率
  17. 远程分支已经不存在的解决办法
  18. Python中的字符串
  19. 媒体报道 | 《数据安全治理自动化技术框架(DSAG)》白皮书诞生,探索数据安全治理技术“最优解”
  20. HHT和FFT的对比

热门文章

  1. 阿里搅局个人网盘市场,为时未晚
  2. 淘宝开放平台php-sdk测试
  3. 基于KNN算法——手写海伦约会(学习)
  4. 朋友圈那些卖网课的资源都是哪来的?靠谱吗?
  5. Go语言学习笔记—golang标准库math包
  6. Orace ITL(Interested Transaction List) 说明
  7. 有人建议苹果收购Netflix?可能钱要打水漂
  8. NYOJ----88汉诺塔
  9. 初接触Directdraw
  10. python爬取文章保存为txt_爬取博主所有文章并保存到本地(.txt版)--python3.6