news 2026/4/20 22:37:06

洛谷-P5658 [CSP-S 2019] 括号树 题解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
洛谷-P5658 [CSP-S 2019] 括号树 题解

值域线段树 + 离线的O(nlog⁡n)O(n\log n)O(nlogn)做法。

题目大意

给定一棵树,每个节点有一个括号。对于每个节点iii,定义sis_isi为从根节点到iii的路径上所有括号按顺序组成的字符串。求每个sis_isi中互不相同的合法括号子串的个数kik_iki

思路

首先,kik_iki可以从父节点递推得到,ki=kfi+aik_i=k_{f_i}+a_iki=kfi+ai。其中aia_iai为以节点iii结尾的合法括号序列数量。因此只要求出每个节点的aaa

经典技巧,将(\texttt{(}(的权值设为111)\texttt{)})设为−1−11,做树上前缀和。设点uuu的前缀和为sumusum_usumu。则以uuu结尾的合法括号子串的开头vvv必须满足:

  1. sumfv=sumusum_{f_v}=sum_usumfv=sumu
  2. 对于v→uv\to uvu这条链上的所有点xxx,有sumx≥sumusum_x\ge sum_usumxsumu

在 DFS 过程中开一棵值域线段树维护1→u1\to u1u这条链上每个sumsumsum值对应的最大节点深度。这样就能找到sump<sumusum_p<sum_usump<sumu且深度最大的节点ppp

ask(x,y)ask(x,y)ask(x,y)表示1→x1\to x1x链上sum=ysum=ysum=y的节点数量。则au=ask(fu,k)−ask(p,k)a_u=ask(f_u,k)-ask(p,k)au=ask(fu,k)ask(p,k)

第一遍 DFS 求出所有询问并离线下来。

第二遍 DFS 求出所有点的aaa

第三遍 DFS 对aaa做树上前缀和得到所有点的kkk即可。

时间复杂度O(nlog⁡n)O(n\log n)O(nlogn)

Code

#include<bits/stdc++.h>#definerept(i,a,b)for(inti(a);i<=b;++i)#definels(p)((p)<<1)#definers(p)((p)<<1|1)#defineebemplace_back#defineintlonglongusingnamespacestd;constexprintN=5e5+5;structQuery{intk,coef,id;// k:目标值// coef:贡献系数,1/-1// id:贡献给到的节点Query(int_k,int_coef,int_id):k(_k),coef(_coef),id(_id){}};structSegTree{intt[N<<3];voidupdate(intp,intpl,intpr,intpos,intx){// 单点修改if(pl==pr)returnvoid(t[p]=x);intmid=pl+pr>>1;if(pos<=mid)update(ls(p),pl,mid,pos,x);elseupdate(rs(p),mid+1,pr,pos,x);t[p]=max(t[ls(p)],t[rs(p)]);}intquery(intp,intpl,intpr,intl,intr){// 区间maxif(l>r)return0;if(l<=pl&&pr<=r)returnt[p];intmid=pl+pr>>1,a=0;if(l<=mid)a=max(a,query(ls(p),pl,mid,l,r));if(mid<r)a=max(a,query(rs(p),mid+1,pr,l,r));returna;}}sgt;chars[N];intsum[N],dep[N],cnt[N<<1],a[N],st[N];intn,m,ans;vector<int>g[N];vector<Query>q[N];voiddfs1(intu){intlst=sgt.query(1,1,m,sum[u],sum[u]);sgt.update(1,1,m,sum[u],dep[u]);st[dep[u]]=u;for(intv:g[u]){sum[v]=sum[u]+(s[v]=='('?1:-1);dep[v]=dep[u]+1;if(s[v]==')'){intbound=sgt.query(1,1,m,1,sum[v]-1);q[u].eb(sum[v],1,v);if(bound)q[st[bound]].eb(sum[v],-1,v);}dfs1(v);}sgt.update(1,1,m,sum[u],lst);}voiddfs2(intu){++cnt[sum[u]];for(Query x:q[u]){a[x.id]+=x.coef*cnt[x.k];}for(intv:g[u])dfs2(v);--cnt[sum[u]];}voiddfs3(intu){for(intv:g[u]){a[v]+=a[u];dfs3(v);}ans^=u*a[u];}signedmain(){cin.tie(0)->sync_with_stdio(0);cin>>n>>s+1;m=n<<1;rept(i,2,n){intx;cin>>x;g[x].eb(i);}g[0].eb(1);sum[0]=n,dep[0]=1;// 为了不出负数,sum统一加上ndfs1(0),dfs2(0),dfs3(0);cout<<ans;return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 22:36:11

【WIFI】WiFi-帧类型与交互流程深度解析

1. 802.11协议帧类型基础认知 每次打开手机连接WiFi时&#xff0c;你可能不会想到背后有一整套精密的通信协议在运作。就像邮局处理信件需要区分平邮、挂号信和快递一样&#xff0c;802.11协议将所有无线通信数据划分为三大类帧&#xff1a;管理帧、数据帧和控制帧。这三种帧各…

作者头像 李华
网站建设 2026/4/20 22:31:09

突破传统操作:Botty如何用AI视觉实现暗黑2重制版自动化刷宝

突破传统操作&#xff1a;Botty如何用AI视觉实现暗黑2重制版自动化刷宝 【免费下载链接】botty D2R Pixel Bot 项目地址: https://gitcode.com/gh_mirrors/bo/botty 厌倦了在《暗黑破坏神II&#xff1a;重制版》中重复枯燥的刷宝操作吗&#xff1f;Botty作为一款专为D2R…

作者头像 李华
网站建设 2026/4/20 22:30:38

基于SpringBoot与Vue开发的学生社团管理平台(含完整源码+部署文档)

温馨提示&#xff1a;文末有联系方式项目名称优化升级 本系统正式命名为「SpringBootVue学生社团管理平台」&#xff0c;编号127&#xff0c;是一款面向高校场景的轻量级、高可用社团信息化管理解决方案&#xff0c;兼顾教学实践与实际业务需求。完整内容清单 包含全部可直接运…

作者头像 李华