Description

有一棵树,要求支持

  1. 查询两点间简单路径的所有子链的异或和的和
  2. 修改某条边的权值

Solution

这种树上异或问题首先应该想到对于每个点存下一个前缀异或和表示这个点到根节点路径的异或和。那么两点之间路径的异或和就等于这两点的前缀和再异或起来。

于是操作一变成了:有k个点,每个点有权值,问\(\sum \limits_{i=1}^k\sum\limits_{j=i+1}^k val[i]\oplus val[j]\)

由于是异或运算,我们按位考虑。

对于二进制位 \(p\),假设这 \(k\) 个数中有 \(x\) 个的第 \(p\) 位为1,剩下的为 \(0\),那么对答案有贡献的实际上就只有 \(x\times (k-x)\) 个点对,也就是说只有这么多点对异或起来的值为 \(1\)。这启示我们对于每个二进制位,都找到多少位是0,多少位是1,把他们乘起来就好了。

Code

#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 30005
using std::min;
using std::max;
using std::swap;
#define int long long
#define ls cur<<1,l,mid,ql,qr
#define rs cur<<1|1,mid+1,r,ql,qr int head[N],dfn[N],top[N],d[N];
int n,m,cnt,tot,lazy[N<<2],cme[N];
int sze[N],son[N],dis[N],fs[N],fa[N]; struct Edge{
int to,nxt,dis;
}edge[N<<1]; struct Node{
int a[12][2]; friend Node operator+(Node x,Node y){
Node z;memset(z.a,0,sizeof z.a);
for(int i=1;i<=10;i++){
z.a[i][0]=x.a[i][0]+y.a[i][0];
z.a[i][1]=x.a[i][1]+y.a[i][1];
} return z;
}
}sum[N<<2]; void add(int x,int y,int z){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].dis=z;
head[x]=cnt;
} inline int getint(){
int X=0;int w=0;char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
} void dfs(int now){
sze[now]=1;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(sze[to]) continue;
d[to]=d[now]+1;
dis[to]=dis[now]^edge[i].dis;cme[to]=edge[i].dis;
dfs(to);sze[now]+=sze[to];fa[to]=now;
if(sze[to]>sze[son[now]])
son[now]=to;
}
} void dfs2(int now,int low){
dfn[now]=++tot;fs[tot]=now;top[now]=low;
if(son[now])
dfs2(son[now],low);
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(dfn[to]) continue;
dfs2(to,to);
}
} void pushup(int cur){
sum[cur]=sum[cur<<1]+sum[cur<<1|1];
} void build(int cur,int l,int r){
if(l==r){
int now=dis[fs[l]];
for(int i=1;i<=10;i++){
if(now>>i-1&1)
sum[cur].a[i][1]++;
else sum[cur].a[i][0]++;
} return;
}
int mid=l+r>>1;
build(cur<<1,l,mid);build(cur<<1|1,mid+1,r);
pushup(cur);
} void pushdown(int cur){
if(!lazy[cur]) return;
for(int i=1;i<=10;i++){
if(lazy[cur]>>i-1&1){
swap(sum[cur<<1].a[i][0],sum[cur<<1].a[i][1]);
swap(sum[cur<<1|1].a[i][0],sum[cur<<1|1].a[i][1]);
}
}
lazy[cur<<1]^=lazy[cur];lazy[cur<<1|1]^=lazy[cur];lazy[cur]=0;
} Node query(int cur,int l,int r,int ql,int qr){
if(ql<=l and r<=qr)
return sum[cur];
int mid=l+r>>1;pushdown(cur);
Node z;memset(z.a,0,sizeof z.a);
if(ql<=mid)
z=z+query(ls);
if(mid<qr)
z=z+query(rs);
return z;
} int ask(int x,int y){
Node z;memset(z.a,0,sizeof z.a);
while(top[x]!=top[y]){
// printf("X=%lld,y=%lld\n",x,y);
if(d[top[x]]<d[top[y]])
swap(x,y);
z=z+query(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(d[x]<d[y]) swap(x,y);
z=z+query(1,1,n,dfn[y],dfn[x]);
int ans=0;
for(int i=1;i<=10;i++)
ans+=(1<<i-1)*z.a[i][0]*z.a[i][1];
return ans;
} void modify(int cur,int l,int r,int ql,int qr,int z){
if(ql<=l and r<=qr){
for(int i=1;i<=10;i++){
if(z>>i-1&1)
swap(sum[cur].a[i][0],sum[cur].a[i][1]);
}
lazy[cur]^=z;return;
}
pushdown(cur);int mid=l+r>>1;
if(ql<=mid)
modify(ls,z);
if(mid<qr)
modify(rs,z);
pushup(cur);
} signed main(){
n=getint(),m=getint();
for(int i=1;i<n;i++){
int x=getint(),y=getint(),z=getint();
add(x,y,z);add(y,x,z);
}
d[1]=1;dfs(1);dfs2(1,1);build(1,1,n);
while(m--){
if(getint()==1){
int x=getint(),y=getint();
printf("%lld\n",ask(x,y));
} else{
int x=getint(),y=getint(),z=getint();
if(d[x]<d[y]) swap(x,y);
modify(1,1,n,dfn[x],dfn[x]+sze[x]-1,cme[x]^z);
cme[x]=z;
}
} return 0;
}

[Luogu 3401] 洛谷树的更多相关文章

  1. [洛谷P3401] 洛谷树

    洛谷题目连接:洛谷树 题目背景 萌哒的Created equal小仓鼠种了一棵洛谷树! (题目背景是辣鸡小仓鼠乱写的QAQ). 题目描述 树是一个无环.联通的无向图,由n个点和n-1条边构成.树上两个 ...

  2. 洛谷树剖模板题 P3384 | 树链剖分

    原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...

  3. Luogu P1738 洛谷的文件夹

    P1738 Luogu 发一个链表题解! 仅有24ms,排名第一哦~ 圆圈代表点,每个店有两个指针,一个指向自己兄弟(同级文件夹),另一个指向自己孩子(子文件夹),还有一个保存当前名字. 有点像二叉树 ...

  4. 让lu哥头痛了许久的代码(洛谷:树的统计)

    错在单点修改时传的是a,应该是id[a](Line 89).谨记!!! //fushao zuishuai #include <cstdio> #include <cstring&g ...

  5. 洛谷P3655 差分数组 树状数组

    题目链接:https://www.luogu.org/problemnew/show/P3655 不一定对,仅供参考,不喜勿喷,不喜勿喷. 先copy洛谷P3368 [模板]树状数组 2 题解里面一位 ...

  6. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  7. 洛谷P2922 [USACO008DEC] 秘密消息Secret Message [Trie树]

    洛谷传送门,BZOJ传送门 秘密消息Secret Message Description     贝茜正在领导奶牛们逃跑.为了联络,奶牛们互相发送秘密信息.     信息是二进制的,共有M(1≤M≤5 ...

  8. 【题解】洛谷P4145 花神游历各国(线段树)

    洛谷P4145:https://www.luogu.org/problemnew/show/P4145 思路 这道题的重点在于sqrt(1)=1 一个限制条件 与正常线段树不同的是区间修改为开方 那么 ...

  9. 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)

    洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...

随机推荐

  1. Spring 框架下 事务的配置(复杂)

    //db.properties配置  src下的文件 jdbc.jdbcUrl=jdbc:mysql:///day43jdbc.driverClass=com.mysql.jdbc.Driverjdb ...

  2. fly插件飞向购物车

    首先载入jQuery库文件和jquery.fly.min.js插件. 插件官方: https://github.com/amibug/fly, 官方例子: http://codepen.io/hzxs ...

  3. Request processing failed; nested exception is java.lang.IllegalStateException: getOutputStream() has already been called for this response

    问题分析: 在ServletRequest servletRequest中已经存在一个项目名称,此时,又用项目名称访问 http://localhost:8080/rent/pdf/preview r ...

  4. vs.code调试node.js的C++扩展

    其实也很简单 点击“Add Configration..”后,会在launch.json增加一个节点,稍调整两个位置 以上完了后,就能在cpp源码里加上自己的断点,执行debug调试我们的C++源代码 ...

  5. 1.1初识python

    1.目前大量的公司都在使用python,功能强大很是牛逼! 2.运维要懂开发,做个全栈的工程师贼牛逼 3.python是一个解释型语言,编译型和解释型的区别是: ①编译型语言由编译器(Compiler ...

  6. windows10环境下安装Tensorflow

    1.什么是tensorflow TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着 ...

  7. 从MATLAB到FPGA 视频和图像处理——讲座学习小结(视频地址https://ww2.mathworks.cn/videos/from-matlab-to-fpga-video-and-image-processing-102492.html)

    1.HDLcoder产品介绍 图像处理分为两个部分: 这里主要讨论第一部分图像处理部分. 一般产品设计流程如下: 适用人群有以下两类: 这里先用一张slider来进行整体概括: 基于模型的设计的好处— ...

  8. 做JAVA开发的同学一定遇到过的爆表问题,看这里解决

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由净地发表于云+社区专栏 记一次Java线上服务器CPU过载问题的排查过程,详解排查过程中用到的Java性能监测工具:jvisualvm ...

  9. unidbgrid 设置 单元格颜色

    unidbgrid 设置 单元格颜色 2018年10月24日 11:32:41 ozhy111 阅读数:68   procedure TF_Resource2.UniDBGrid1DrawColumn ...

  10. Nextday 参数化单元测试(测试用例)设计

    一.首先简单描述一下下载试题及配置试题的过程 配置环境:安装Eclipse.JDK(1.7).及考试插件 (net.mooctest....*.jar)等: 登录系统:运行Eclipse: [Mooc ...