题目


分析(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 卷] 树的更多相关文章

  1. 洛谷P6623——[省选联考 2020 A 卷] 树

    传送门:QAQQAQ 题意:自己看 思路:正解应该是线段树/trie树合并? 但是本蒟蒻啥也不会,就用了树上二次差分 (思路来源于https://www.luogu.com.cn/blog/dengy ...

  2. 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)

    题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...

  3. [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂

    题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...

  4. luoguP6623 [省选联考 2020 A 卷] 树(trie树)

    luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...

  5. 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)

    洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\)​ 算法通过,因此可以考虑 \(\mathcal O(n^2 ...

  6. 洛谷 P7515 - [省选联考 2021 A 卷] 矩阵游戏(差分约束)

    题面传送门 emmm--怎么评价这个题呢,赛后学完差分约束之后看题解感觉没那么 dl,可是现场为啥就因为种种原因想不到呢?显然是 wtcl( 先不考虑"非负"及" \(\ ...

  7. 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)

    洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\)​ \(10^9\)​ 的时代了吗?落伍了落伍了/ ...

  8. dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)

    qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...

  9. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

  10. 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)

    题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做“LCT” 的挑 ...

随机推荐

  1. win32 - 虚拟内存的一些介绍

    对32位Windows来说,其虚拟地址空间总数就是2的32次方,即4GB. 如果没有在引导时加上/3GB或/BOOTVA选项,Windows默认最大会分2GB给内核模式程序使用,2GB给用户模式程序. ...

  2. 常用Linux命令备查

    查找在指定日期创建的文件 2种方式: find命令: # 这种方式查找到的文件会显示路径 find -name *.log -newermt '2022-06-21 08:00:00' ! -newe ...

  3. 【C++ OOP 03 友元】各种友元例子以及如何类外写成员函数

    [友元] 在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术 友元的目的就是让一个函数或者类 访问另一个类中私有成员 友元的关键字为 friend 友元的三种实现 全 ...

  4. 【Azure 应用服务】App Service for Linux环境中,如何解决字体文件缺失的情况

    问题描述 部署在App Service for Linux环境中的Web App.出现了字体文件缺失的问题,页面显示本来时中文的地方,区别变为方框占位. 问题分析 在应用中,通常涉及到显示问题的有两个 ...

  5. 【Azure 媒体服务】记录一个简单的媒体视频上传到Media Service无法播放问题

    问题描述 从本地上传到Azure Media Service Portal的视频,并且新增定位符后,无法播放.但是上传的其他视频是可以的.疑惑中!! 问题自查 自查发现,是视频的文件名中有个特殊符号. ...

  6. MVVM框架模式

    MVC框架模式 MVP框架模式 MVVM框架模式 MVVM模式即: 1.Model:数据层.网络数据操作,file文件操作,本地数据库操作: 2.View:视图层.布局加载,ui交互. 3.ViewM ...

  7. Vue3学习(二十一)- 文档管理页面布局修改

    写在前面 按照国际惯例,要先聊下生活,吐槽一番,今天是2月14日,也是下午听老妈说,我才知道! 现在真的是对日期节日已经毫无概念可言,只知道星期几. 现在已经觉得写博客也好,学习文章也罢,和写日记一样 ...

  8. Java //输入两个正整数m和n,求其最大的公约数和最小公倍数//12和20的最大公约数是4,最小公倍数是60

    1 //输入两个正整数m和n,求其最大的公约数和最小公倍数 2 //12和20的最大公约数是4,最小公倍数是60 3 4 Scanner scan = new Scanner(System.in); ...

  9. Python列表转换成字典、嵌套列表转字典、多个列表转为字典嵌套列表

    目录 两列表转为字典 多列表转为字典嵌套列表 嵌套列表转字典 方法一:直接内置dict 方法二: for循环 一个列表转字典 两列表转为字典 list1=["key1"," ...

  10. [学习笔记]Linux + Nginx环境下部署 Web 站点

    ​部署后端程序,请阅读: [学习笔记]Linux环境下部署 .Net5 程序 - 林晓lx - 博客园 (cnblogs.com) 打包项目 以Vue项目为例,首先打包站点,前往项目的根目录并键入: ...