Codeforces 842 D Vitya and Strange Lesson
来源:互联网 发布:php编写99乘法表 编辑:程序博客网 时间:2024/06/05 17:45
题目地址
题意:告诉你一个序列,然后给你m个操作,每个操作就是把这个序列异或上x,然后再得出最小的没有在这个序列中出现的数。
思路:因为异或的定义就是转成2进制的形式,每一位相同的为0,不同的为1。这样的话我们就可以把数转化为二进制存入字典树(二叉树,向左为0向右为1)中,异或的话就是把异或的数转成二进制的形式,把该位为1的翻转一下字典树节点的两个子节点就好了。查询的时候就是一直往左找,直到下面的数是满的就转到右子树去找(这个理解不了可以看下我代码结构体部分的注释),最后得到的结果就是最小的数。(注意因为最大的数才为3*10^5所以20层就好了,不会出现超过20层的情况,然后转成二进制以后要在前面补0,这样就比较好在字典树中存值了)
#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 300010#define M 2//每个节点的子节点的个数#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int n, m;int num[N];struct node { int cnt, res;//cnt存的是它下面有多少个数,就是查询的时候判断这边的数是不是已经完全都有了,res就是记录异或的值,想当与一个延迟标记省时间 node *next[M]; void init() { for (int i = 0; i < M; i++) { next[i] = NULL; } res = 0; cnt = 0; }};void push_down(node *p, int d) {//异或时反转左右孩子,向下传递 for (int i = 0; i < M; i++) { if (p->next[i]) { p->next[i]->res ^= p->res; } } if ((p->res >> d) & 1) { swap(p->next[0], p->next[1]); } p->res = 0;}struct Trie { void insert(node *root, int num) {//需要自定义 node *p = root; p->cnt++; for (int i = 20; ~i; i--) { int k = (num >> i) & 1; if (p->next[k] == NULL) { p->next[k] = new node; p->next[k]->init(); } p = p->next[k]; p->cnt++; } } int solve(node *root) { node *p = root; int ans = 0; for (int i = 20; ~i; i--) { push_down(p, i); if (p->next[0] == NULL || (p->next[0] != NULL&&p->next[0]->cnt != (1 << i))) { p = p->next[0]; } else { p = p->next[1]; ans += 1 << i; } if (p == NULL) return ans; } } void Free(node *p) { for (int i = 0; i < M; i++)if (p->next[i]) Free(p->next[i]); delete p; }}tree;int main() { cin.sync_with_stdio(false); node *root; while (cin >> n >> m) { for (int i = 0; i < n; i++) { cin >> num[i]; } sort(num, num + n); n = unique(num, num + n) - num; root = new node; root->init(); for (int i = 0; i < n; i++) { tree.insert(root, num[i]); } for (int i = 0; i < m; i++) { int k; cin >> k; root->res ^= k; cout << tree.solve(root) << endl; } tree.Free(root); } return 0;}
阅读全文
0 0
- codeforces 842D. Vitya and Strange Lesson
- Codeforces 842D Vitya and Strange Lesson
- Codeforces 842 D Vitya and Strange Lesson
- CodeForces 842D Vitya and Strange Lesson
- Codeforces 842 D. Vitya and Strange Lesson (trie)
- Codeforces 842 D Vitya and Strange Lesson 线段树
- D. Vitya and Strange Lesson
- Codeforces Round #430 (Div. 2) D. Vitya and Strange Lesson
- Codeforces Round #430 (Div. 2) D. Vitya and Strange Lesson
- Codeforces Round #430 (Div. 2) D. Vitya and Strange Lesson
- Codeforces Round #430 (Div. 2) D. Vitya and Strange Lesson
- [Codeforces 842D Vitya and Strange Lesson]异或字典树
- Codeforces 842D Vitya and Strange Lesson【逆向思维+字典树查询亦或最小值】
- Codeforces 842 D Vitya and Strange Lesson 线段树 (未理解透)
- CF 842D Vitya and Strange Lesson 01Trie(mex)
- 【Codeforces Round #430 (Div. 2) D】 D. Vitya and Strange Lesson ("带lazy" 的字典树)
- Codeforces Round #430 (Div. 2) D. Vitya and Strange Lesson [trie]
- Codeforces Round #430 (Div. 2):D. Vitya and Strange Lesson(模拟建树)
- 经典排序算法相关知识
- Loadrunner中参数和变量的使用
- PLSQL使用技巧----加快你的编程效率
- Git-时光穿梭
- 去哪儿网任务系统演进
- Codeforces 842 D Vitya and Strange Lesson
- windows安装git
- 【MYSQL】查询不区分大小写
- 51nod 1091 线段的重叠
- bigDecimal作为参数传入方法中累加的坑
- ios水波纹效果
- Gti学习中“Please tell me who you are.”的解决
- UITableView什么时候使用,UITableView的使用条件使用场景,哪些情况不需要使用UITableView
- qt 通过http获取网络图片并且显示