#树上差分 or 01-Trie#洛谷 6623 [省选联考 2020 A 卷] 树
分析(01trie)
考虑用trie做需要满足什么操作:加入某个数、01-Trie的合并、全局加一。
主要是全局加一比较难做,考虑改变的地方就是 \(X*2^T+2^T-1\)。
把01-Trie倒着建,那么全局加一只需要交换左右儿子并往原来的右儿子更新就可以了
再考虑这样建如何维护信息,那么就是 \(w[trie[x][0]]*2\) \(xor\) \(w[trie[x][1]]*2\) xor \(cnt[trie[x][1]]\)
也许这个能更好启发树上差分的做法吧
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=530011,M=N*21; long long Ans;
struct node{int y,next;}e[N]; bool _w[M];
int ans[N],a[N],as[N],n,cnt,trie[M][2],rt[N],w[M];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void pup(int rt){
_w[rt]=_w[trie[rt][0]]^_w[trie[rt][1]];
w[rt]=(w[trie[rt][0]]^w[trie[rt][1]])<<1|_w[trie[rt][1]];
}
void update(int &rt,int x,int z){
if (!rt) rt=++cnt;
if (z>20){
_w[rt]^=1;
return;
}
update(trie[rt][(x>>z)&1],x,z+1);
pup(rt);
}
void one(int rt){
swap(trie[rt][0],trie[rt][1]);
if (trie[rt][0]) one(trie[rt][0]);
pup(rt);
}
int Merge(int fi,int se){
if (!fi||!se) return fi|se;
w[fi]^=w[se],_w[fi]^=_w[se];
trie[fi][0]=Merge(trie[fi][0],trie[se][0]);
trie[fi][1]=Merge(trie[fi][1],trie[se][1]);
return fi;
}
void dfs(int x){
for (int i=as[x];i;i=e[i].next)
dfs(e[i].y),rt[x]=Merge(rt[x],rt[e[i].y]);
one(rt[x]),update(rt[x],a[x],0);
ans[x]=w[rt[x]];
}
int main(){
n=iut();
for (int i=1;i<=n;++i) a[i]=iut();
for (int i=2;i<=n;++i){
int x=iut();
e[i]=(node){i,as[x]},as[x]=i;
}
dfs(1);
for (int i=1;i<=n;++i) Ans+=ans[i];
return !printf("%lld",Ans);
}
分析(树上差分)
改变的地方就是 \(X*2^T+2^T-1\),那么可以拆位考虑,
将子树的答案合并上来时,只有这些位置会改变。
如果记 \(a'_x=a_x+dep_x\),那么对于每个二进制位 子树中 \(dep_x\) 这个位置实则是要改变的,
因为插入 \(a_y+dep_x+1\) 后如果该值与 \(dep_x\) 在某个二进制位下与 \(2^i-1\) 同余那么它需要改变
树上差分就是用总的改变位置异或非子树改变位置即可
代码
#include <cstdio>
#include <cctype>
using namespace std;
const int N=530011; struct node{int y,next;}e[N];
int ans[N],a[N],as[N],w[N<<1][21],n,two[21]; long long Ans;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void dfs(int x,int d){
ans[x]=a[x];
for (int i=0;i<21;++i) w[(d+a[x])&(two[i]-1)][i]^=two[i];
for (int i=0;i<21;++i) ans[x]^=w[d&(two[i]-1)][i];
for (int i=as[x];i;i=e[i].next)
dfs(e[i].y,d+1),ans[x]^=ans[e[i].y];
for (int i=0;i<21;++i) ans[x]^=w[d&(two[i]-1)][i];
}
int main(){
n=iut(),two[0]=1;
for (int i=1;i<21;++i) two[i]=two[i-1]<<1;
for (int i=1;i<=n;++i) a[i]=iut();
for (int i=2;i<=n;++i){
int x=iut();
e[i]=(node){i,as[x]},as[x]=i;
}
dfs(1,0);
for (int i=1;i<=n;++i) Ans+=ans[i];
return !printf("%lld",Ans);
}
#树上差分 or 01-Trie#洛谷 6623 [省选联考 2020 A 卷] 树的更多相关文章
- 洛谷P6623——[省选联考 2020 A 卷] 树
传送门:QAQQAQ 题意:自己看 思路:正解应该是线段树/trie树合并? 但是本蒟蒻啥也不会,就用了树上二次差分 (思路来源于https://www.luogu.com.cn/blog/dengy ...
- 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)
题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...
- [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂
题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)
洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\) 算法通过,因此可以考虑 \(\mathcal O(n^2 ...
- 洛谷 P7515 - [省选联考 2021 A 卷] 矩阵游戏(差分约束)
题面传送门 emmm--怎么评价这个题呢,赛后学完差分约束之后看题解感觉没那么 dl,可是现场为啥就因为种种原因想不到呢?显然是 wtcl( 先不考虑"非负"及" \(\ ...
- 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)
洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\) \(10^9\) 的时代了吗?落伍了落伍了/ ...
- dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)
qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...
- 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)
题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...
- 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)
题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做“LCT” 的挑 ...
随机推荐
- mysql安装及增删改查操作---day35
# ### mysql ''' 命令可以用tab来补全 d: D:\>cd MySQL5.7 D:\>cd D:\MySQL5.7\mysql-5.7.25-winx64\bin 直接切换 ...
- 都说了别用BeanUtils.copyProperties,这不翻车了吧
分享是最有效的学习方式. 博客:https://blog.ktdaddy.com/ 故事 新年新气象,小猫也是踏上了新年新征程,自从小猫按照老猫给的建议[系统梳理大法]完完整整地梳理完毕系统之后,小猫 ...
- 基于javaweb的个人音乐网站
一 .需求 ① 前台用户: 用户注册和登录以及完善个人资料: 添加好友功能(用户之间可通过发送好友申请添加好友,被添加人可以同意或拒绝好友申请): 下载歌曲功能(当用户点击下载按钮时,就能下载相对应的 ...
- 1.Go 的基本数据类型
Go 的基本数据类型
- 【LeetCode字符串#extra】KMP巩固练习:旋转字符串、字符串轮转
旋转字符串 https://leetcode.cn/problems/rotate-string/ 给定两个字符串, s 和 goal.如果在若干次旋转操作之后,s 能变成 goal ,那么返回 tr ...
- sql组合索引怎样使用?怎样命中?
一.联合索引的使用 本文中联合索引的定义为(MySQL): ALTER TABLE table_name ADD INDEX (col1,col2,col3); 二.联合索引的本质 当创建(col1, ...
- 「实操」结合图数据库、图算法、机器学习、GNN 实现一个推荐系统
本文是一个基于 NebulaGraph 上图算法.图数据库.机器学习.GNN 的推荐系统方法综述,大部分介绍的方法提供了 Playground 供大家学习. 基本概念 推荐系统诞生的初衷是解决互联网时 ...
- 智能升级:AntSK教你如何让聊天机器人实现智能联网操作
随着人工智能技术的飞速发展,智能体已经逐步融入到我们的日常生活中.不过,要想让智能体不仅能聊天,还能接入网络实时获取信息,为我们提供更多便利,所需技术的复杂性不得不让人瞩目.今天,我将和各位分享如何在 ...
- linux下查看文件时显示行号
1.用 vi 或 vim 打开文件后显示行号: 显示当前行号: :nu 显示所有行号: :set nu 2.设置服务器显示行号 2.1:编辑~/.vimrc文件,在该文件中加入 ...
- wsl使用记录
# wsl使用记录 安装 直接参考微软官方文档使用 WSL 在 Windows 上安装 Linux ubuntu可用发行版安装 https://ubuntu.com/wsl 访问 方式一:在资源管理器 ...