题目分析

首先,我们删掉所有被Hack的点,剩下的点的父亲,为原树上它的第一个没有被Hack的祖先。则产生了一个森林。

那么对于这个游戏局面,sg值为每棵树的sg值的异或和。

现在考虑一棵树的sg怎么算。记g(x)g(x)g(x)为在这棵树中选一个节点xxx,将xxx与其祖先全部删除,剩下的子树们的sg异或和。那么该树中所有g(x)g(x)g(x)的mex就是该树的sg。

我们发现,假设我们现在在处理子树xxx,处理子树yyy(yyy为xxx的父亲)的时候,子树xxx中所有节点的g(x)g(x)g(x)都要异或yyy除了xxx以外的儿子们的sg值。于是考虑用trie树来维护g(x)g(x)g(x),异或就只要打标记就可以了。

然后做trie树合并获得yyy的trie树,我们知道trie树合并的复杂度是O(nlog⁡n)O(n\log n)O(nlogn)的。

再插入所有yyy的所有儿子异或和,即g(y)g(y)g(y)。

求出整棵trie树的mex,方法是记录trie树中以每个节点为根的子树是否是满的,如果是当前节点的左子树是满的,则在右子树中寻找这个mex值,否则在左子树中找。(往左走的边是0,往右走的边是1)

为了获得答案,我们还要记录每个g(x)g(x)g(x)值对应的xxx,这个只要对于trie树上的每个叶子节点开一个链表即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {int q=0;char ch=' ';while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();return q;
}
const int N=100005,mxd=25;
int c[N],h[N],ne[N<<1],to[N<<1],fa[N],sg[N],st[N];
int bin[35],s[N*25][2],full[N*25],rt[N],tag[N*25],fir[N*25],nxt[N],tail[N*25];
int n,tot,ans,SZ,top,debug;void puttag(int x,int num,int d) {if(num&bin[d]) swap(s[x][0],s[x][1]);tag[x]^=num;
}
void pd(int x,int d) {if(s[x][0]) puttag(s[x][0],tag[x],d-1);if(s[x][1]) puttag(s[x][1],tag[x],d-1);tag[x]=0;
}
void up(int x) {full[x]=full[s[x][0]]&full[s[x][1]];}
int merge(int x,int y,int d) {if(!x||!y) return x|y;if(d<0) {nxt[tail[x]]=fir[y],tail[x]=tail[y];return x;}if(tag[x]) pd(x,d); if(tag[y]) pd(y,d);s[x][0]=merge(s[x][0],s[y][0],d-1);s[x][1]=merge(s[x][1],s[y][1],d-1);up(x);return x;
}
void ins(int &x,int d,int num,int id) {if(!x) x=++SZ;if(d<0) {full[x]=1;if(!fir[x]) fir[x]=tail[x]=id;else nxt[tail[x]]=id,tail[x]=id;return;}if(tag[x]) pd(x,d);if(num&bin[d]) ins(s[x][1],d-1,num,id);else ins(s[x][0],d-1,num,id);up(x);
}
int mex(int x,int d) {if(d<0) return 0;if(tag[x]) pd(x,d);if(!full[s[x][0]]) return mex(s[x][0],d-1);else return bin[d]+mex(s[x][1],d-1);
}
void work(int x) {int sum=0;for(RI i=h[x];i;i=ne[i]) work(to[i]),sum^=sg[to[i]];for(RI i=h[x];i;i=ne[i]) puttag(rt[to[i]],sum^sg[to[i]],mxd);for(RI i=h[x];i;i=ne[i]) rt[x]=merge(rt[x],rt[to[i]],mxd);ins(rt[x],mxd,sum,x),sg[x]=mex(rt[x],mxd);
}
void getans(int x,int d,int num) {if(d<0) {for(RI i=fir[x];i;i=nxt[i]) st[++top]=i;return;}if(tag[x]) pd(x,d);if(num&bin[d]) getans(s[x][1],d-1,num);else getans(s[x][0],d-1,num);
}void add(int x,int y) {to[++tot]=y,ne[tot]=h[x],h[x]=tot;}
void dfs(int x,int las,int OvO) {fa[x]=OvO;for(RI i=h[x];i;i=ne[i]) {if(to[i]==las) continue;if(!c[x]) dfs(to[i],x,x);else dfs(to[i],x,OvO);}
}
int main()
{int x,y;n=read();bin[0]=1;for(RI i=1;i<=mxd;++i) bin[i]=bin[i-1]<<1;for(RI i=1;i<=n;++i) c[i]=read();for(RI i=1;i<n;++i) x=read(),y=read(),add(x,y),add(y,x);dfs(1,0,0);tot=0;for(RI i=1;i<=n;++i) h[i]=0;for(RI i=1;i<=n;++i) if(!c[i]&&fa[i]) add(fa[i],i);for(RI i=1;i<=n;++i) if(!c[i]&&!fa[i]) work(i),ans^=sg[i];if(!ans) puts("-1");else {for(RI i=1;i<=n;++i)if(!c[i]&&!fa[i]) getans(rt[i],mxd,ans^sg[i]);sort(st+1,st+1+top);for(RI i=1;i<=top;++i) printf("%d\n",st[i]);}return 0;
}

bzoj4134 ljw和lzr的hack比赛 trie树合并相关推荐

  1. Trie树合并 + SG函数 ---- BZOJ4730. Alice和Bob又在玩游戏(动态开点Trie 树上全局异或标记 + 合并 + 博弈论)

    题目大题 题目大意: 解题思路: 首先我们对于子树u的SG函数为SG函数为SG函数为 ⨁是异或和\bigoplus是异或和⨁是异或和 SG[u]=mex{⨁w∈(w的父亲在u到v的路径上)SG[w]∣ ...

  2. trie树的数据结构_C / C ++中的Trie数据结构

    trie树的数据结构 A Trie data structure acts as a container for a dynamic array. In this article, we shall ...

  3. Trie树 -- 高效的字典树

    文章目录 简介 原理 构造一棵Trie树 使用Trie树进行查询 实现 模拟(瞎暴力)实现 空间优化 简介 Trie树是一种数据结构,它有一个好听的中文名字,叫"字典树".顾名思义 ...

  4. usaco Cowxor (trie 树)

    没想到trie树还可以用在这上面,厉害厉害. [分析]这是字母树的经典应用.首先因为是求xor的最大值,可以用前缀和计算xor值,然后n^2枚举即可. [cpp] view plaincopy for ...

  5. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

  6. 字符串匹配数据结构 --Trie树 高效实现搜索词提示 / IDE自动补全

    文章目录 1. 算法背景 2. Trie 树实现原理 2.1 Trie 树的构建 2.2 Trie树的查找 2.3 Trie树的遍历 2.4 Trie树的时间/空间复杂度 2.5 Trie 树 Vs ...

  7. POJ 2418 Hardwood Species(trie 树)

    题目链接 开始想用map的,字典序不会搞,还是老老实实的用trie树把.好久没写了,忘得差不多了. 1 #include <iostream> 2 #include <cstdio& ...

  8. 【bzoj3261】最大异或和 可持久化Trie树

    题目描述 给定一个非负整数序列 {a},初始长度为 N.        有M个操作,有以下两种操作类型: 1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2.Q l r x: ...

  9. 算法 | 动画+解析,轻松理解「Trie树」

    Trie这个名字取自"retrieval",检索,因为Trie可以只用一个前缀便可以在一部字典中找到想要的单词. 虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 ...

  10. 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树......

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 上篇文章我们主要介绍了线性数据结构,本篇233酱带大家看看 无所不 ...

最新文章

  1. 大神开发arXiv全新H5版,一步告别公式排版错误,手机也能轻松看文献
  2. HTTP缓存原理介绍
  3. [转]要有梦----送给自己,希望自己能尽快走出当前的痛苦期
  4. kylin与superset整合
  5. cookie注入讲解
  6. python logger设置信息取得_shell 脚本中如何获取 python logging 打印的信息?
  7. 【C语言】用C语言输出“心形”图案
  8. CSDN2013博客之星评选(求投票支持)
  9. java虚拟机之一内存运行时数据区域解释
  10. 单双号限行,今天是否绿色出行
  11. python __init__(self)_python中的_init_和self是什么的关系?
  12. GitHub创建个人主页
  13. freeswitch 文件包含关系图
  14. 【Linux】Linux设备驱动开发详解:基于最新的Linux 4.0内核
  15. 蛋白质降解技术中常用的蛋白酶(一)
  16. PS--用法/快捷键
  17. 在IDEA里jsp项目图片显示不出来(图文解答)
  18. python爬取头条视频_Python爬虫:爬取某日头条某瓜视频,有/无水印两种方法
  19. 博达交换机S2528PB常用配置命令
  20. RAID技术详解与总结

热门文章

  1. 计算机应用与维修电竞与管理,电子竞技运动与管理-五年制高技招生专业-广州市白云工商技师学院_广州市白云工商高级技工学校_信息工程系(计算机系)...
  2. 宝塔面板切换PHP版本
  3. PPT如何导出高质量图片
  4. 神策数据杨宁:券商财富管理数字化转型客户全生命周期(视频解读)
  5. 使用亚马逊云快速托管静态网站
  6. 数据结构试卷及答案(七)
  7. FindBugs的使用
  8. 优秀的网站加速插件 – WP rocket详细设置教程
  9. iOS开发之App Icon(整套)生成工具App Icon Gear
  10. SaaS行业其实岌岌可危