news 2026/7/10 15:14:45

洛谷 P5556 圣剑护符 题解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
洛谷 P5556 圣剑护符 题解

题目概括:

给定一棵n nn个节点的树,每个节点有一个初始权值v i v_ivi(范围为[ 0 , 2 30 ) [0, 2^{30})[0,230))。需要处理q qq
次操作,操作分为两种:

  1. 修改操作Update x y z:将节点x xxy yy的简单路径上所有节点的权值异或上z zz
  2. 查询操作Query x y:询问从节点x xxy yy的简单路径上的所有节点权值组成的集合中,是否存在两个不相等的子集(子集指节点集合的子集,空集也包含在内),使得这两个子集中所有节点权值的异或和相等。如果存在输出
    YES,否则输出NO

问题等价于:判断路径上的所有节点权值在异或意义下是否线性相关(即是否存在一个非空子集的异或和为0 00)。由于权值位数不超过30 3030,若路径长度大于30 3030,根据鸽巢原理必然线性相关,答案一定为YES;否则需要实际检查这些权值是否线性相关。
From DeepSeek

简单来说,你需要实现的是:对于一颗树,你需要实现快速的单链异或+单点查询。

那我们如果想快速完成操作,就想到把修改的东西放到一个区间内,用线段树维护这样一段区间的复杂度时O ( log ⁡ 2 n ) O(\log_2 n)O(log2n)的。那如何把一条链放到一个区间内呢?

树链剖分!

考虑一下,如果我们在进行重链剖分的同时计算 DFS 序,那么同一条重链上的结点的时间戳一定是连续的。

所以修改的时候,我们用类似求 LCA 的方法进行操作,每次更新这条重链时间戳所对应的区间,然后跳到当前链链头的父亲。

这样我们就在O ( log ⁡ 2 n ) O(\log_2 n)O(log2n)处理了一个区间,而树链剖分在最坏情况下会有log ⁡ 2 n \log_2 nlog2n个区间,所以插入的时间复杂对时O ( log ⁡ 2 2 n ) O(\log_2^2n)O(log22n)级别的。

考虑查询。这里用到一个 trick。如果集合的规模很大,那么答案必然有解。这道题,树上所有结点的权值小于2 30 2^{30}230,这意味着如果在31 3131个里面选择一些,一共有2 31 2^{31}231种方案,根据抽屉原理,必然有一种满足要求的方案。

对于l e n ≤ 30 len \le 30len30的部分来说,考虑异或空间线性基的性质,显然基中不能出现异或值为0 00的数。这意味着有两个方法表示同一个数。故一定有方法使两个子集的异或和相同。

#include<bits/stdc++.h>#definels(p<<1)#definers(p<<1|1)usingll=longlong;constexprintN=1e5+5;std::vector<int>adj[N];structSegment_Tree{structNode{intnum,l,r;inttag;}t[N<<2];voidbuild(intp,intpl,intpr){t[p].l=pl;t[p].r=pr;t[p].num=t[p].tag=0;if(pl==pr)return;intmid=pl+pr>>1;build(ls,pl,mid);build(rs,mid+1,pr);}voidpush_down(intp){if(t[p].tag){t[ls].tag^=t[p].tag;t[ls].num^=t[p].tag;t[rs].tag^=t[p].tag;t[rs].num^=t[p].tag;t[p].tag=0;}}voidupdate(intp,intl,intr,intval){if(t[p].l>r||t[p].r<l)return;if(l<=t[p].l&&t[p].r<=r){t[p].num^=val;t[p].tag^=val;return;}push_down(p);update(ls,l,r,val);update(rs,l,r,val);}intquery(intp,intpos){if(t[p].l==t[p].r)returnt[p].num;push_down(p);intmid=t[p].l+t[p].r>>1;if(pos<=mid)returnquery(ls,pos);elsereturnquery(rs,pos);}voidprint(intp){if(t[p].l==t[p].r)std::cout<<t[p].num<<" ";elsepush_down(p),print(ls),print(rs);}}tree;intfa[N],dep[N],siz[N],top[N],dfn[N],v[N];inttim;voiddfs1(intu,intf){fa[u]=f;dep[u]=dep[f]+1;siz[u]=1;for(intv:adj[u]){if(v!=f){dfs1(v,u);siz[u]+=siz[v];}}}voiddfs2(intu,intf){top[u]=f;dfn[u]=++tim;intmx=-1,s=-1;tree.update(1,tim,tim,v[u]);for(intv:adj[u]){if(v!=fa[u]&&siz[v]>mx){mx=siz[v];s=v;}}if(s!=-1)dfs2(s,f);for(intv:adj[u]){if(v!=fa[u]&&v!=s)dfs2(v,v);}}voidupdate(intx,inty,intval){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])std::swap(x,y);tree.update(1,dfn[top[x]],dfn[x],val);x=fa[top[x]];}if(dfn[x]>dfn[y])std::swap(x,y);tree.update(1,dfn[x],dfn[y],val);}intlca(intu,intv){while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]])v=fa[top[v]];elseu=fa[top[u]];}if(dep[u]<dep[v])returnu;returnv;}constexprintM=31;structleaner_basis{intb[M];voidinit(){memset(b,0,sizeofb);}boolinsert(intx){for(inti=M-1;i>=0;i--){if(!(x&(1<<i)))continue;if(!b[i]){b[i]=x;return1;}x^=b[i];}returnfalse;}}basis;intn,q,x,y,z;intmain(){std::cin>>n>>q;for(inti=1;i<=n;i++)std::cin>>v[i];for(inti=1;i<n;i++){intu,v;std::cin>>u>>v;adj[u].push_back(v);adj[v].push_back(u);}tree.build(1,1,n);dfs1(1,0);dfs2(1,1);while(q--){std::string s;std::cin>>s>>x>>y;if(s[0]=='U'){std::cin>>z;update(x,y,z);}else{intl=lca(x,y);intdis=dep[x]+dep[y]-2*dep[l]+1;if(dis>30)std::cout<<"YES\n";else{basis.init();boolflag=false;if(!basis.insert(tree.query(1,dfn[l])))flag=1;if(!flag)while(x!=l){if(!basis.insert(tree.query(1,dfn[x]))){flag=1;break;}x=fa[x];}if(!flag)while(y!=l){if(!basis.insert(tree.query(1,dfn[y]))){flag=1;break;}y=fa[y];}std::cout<<(flag?"YES\n":"NO\n");}}}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/10 9:40:26

【API 设计之道】06 结构化错误处理:RFC 7807 与错误模型的最佳实践

大家好&#xff0c;我是Tony Bai。欢迎来到我们的专栏 《API 设计之道&#xff1a;从设计模式到 Gin 工程化实现》的第六讲。在前面的课程中&#xff0c;我们讨论了如何设计 URL、如何传输数据、如何分页。今天&#xff0c;我们来聊聊一个略显沉重但绝对避不开的话题&#xff1…

作者头像 李华
网站建设 2026/7/10 9:38:35

投递 2 天,拿下 Offer!

大家好&#xff0c;我是R哥。今天分享一个史上最快拿 Offer 的案例&#xff0c;投递 2 天拿下 Offer&#xff0c;兄弟直接说&#xff1a;“回本了 我这才刚投两天&#xff01;”。&#xff08;他史上最快&#xff0c;我们辅导案例并不是最快的。&#xff09;这兄弟工作快 10 年…

作者头像 李华
网站建设 2026/7/10 13:45:27

终极Kafka-UI快速部署指南:5分钟搞定可视化监控

终极Kafka-UI快速部署指南&#xff1a;5分钟搞定可视化监控 【免费下载链接】kafka-ui provectus/kafka-ui: Kafka-UI 是一个用于管理和监控Apache Kafka集群的开源Web UI工具&#xff0c;提供诸如主题管理、消费者组查看、生产者测试等功能&#xff0c;便于对Kafka集群进行日常…

作者头像 李华
网站建设 2026/7/10 9:41:56

Python:接口隔离原则(ISP)

接口隔离原则&#xff08;Interface Segregation Principle&#xff0c;ISP&#xff09;强调&#xff1a;客户端不应该被迫依赖它不需要的方法。换句话说&#xff0c;一个接口&#xff08;或抽象类&#xff09;应该尽可能小而精&#xff0c;不应把不相关的功能塞进同一个接口里…

作者头像 李华
网站建设 2026/7/10 14:55:16

3步告别糊涂账:开源记账系统如何帮你重建财务秩序

"钱都花到哪里去了&#xff1f;"这可能是很多人月底最常问自己的问题。工资刚到手就所剩无几&#xff0c;想存钱却总是存不下来&#xff0c;想要投资理财却连自己的收支状况都搞不清楚。这种财务混乱的状况&#xff0c;正在影响越来越多人的生活品质。 【免费下载链接…

作者头像 李华
网站建设 2026/7/9 15:21:14

C++ MFC Qt《高级程序设计实践》任务书(10题)[2025-12-16]

C MFC Qt《高级程序设计实践》任务书(10题)[2025-12-16] 《高级程序设计实践》 任务书 1. 基本要求 1)编写图形化界面&#xff0c;界面友好、美观 2)注意数据结构和程序结构的设计 3)注意程序的可读性和可扩展性 4)原则上不得使用全局变量 5)完成6-10个核心功能&#xff0c;代…

作者头像 李华