当前位置: 首页 > news >正文

洛谷-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;}
http://www.jsqmd.com/news/673511/

相关文章:

  • 如何为ClearURLs创建自定义规则:保护隐私的终极指南
  • 从频域看高斯滤波:用Python+NumPy手把手带你理解sigma如何决定图像‘模糊度’
  • 《jEasyUI 创建复杂树形网格》
  • Deforum Stable Diffusion终极指南:从零开始掌握AI动画生成
  • 深入uvmgen生成的UVM环境:如何从“空壳”到“实战”的改造指南
  • 关于测试之理论
  • Ace Data Cloud Flux 图像生成 API 使用指南
  • PySide6多线程避坑指南:除了QThread,别忘了还有QtConcurrent和QRunnable
  • 终极系统定制方案:3步解锁设备隐藏潜力
  • 5分钟掌握WinUtil:Windows系统优化与软件管理的终极工具箱
  • AI驱动无线网络人才短缺危机加剧,企业安全风险攀升
  • 大模型推理:决胜未来的三大核心技术战场
  • Dify .NET SDK官方未适配AOT?别等了!我们已验证通过的6大手动补丁方案(含Source Generator注入实战)
  • ORB-SLAM3的Atlas多地图系统到底强在哪?手把手解析其重定位与地图合并的工程实现
  • Jetson Nano到手后,除了SSH连接,这3个远程管理技巧让你效率翻倍
  • 我又读了一次白夜行
  • THREE.MeshLine与Three.js生态系统集成:最佳实践和常见问题解决方案
  • Materialistic中的响应式编程:RxJava与RxAndroid实战指南
  • CSS如何制作导航栏平滑移动_使用transition与left属性
  • HarmonyOS / OpenHarmony 鸿蒙PC平台三方库移植:使用 Lycium 移植 pngquant 的实践总结
  • 如何配置Oracle 19c CDB资源管理_PDB级别的CPU与内存限制
  • 从LeetCode实战看C++ STL:用unordered_set优化你的算法(附高频题解析)
  • 避开这些坑:在Ubuntu for Raspberry Pi上成功安装OpenPLC运行时的完整指南
  • 避坑指南:JMeter JDBC配置连接MySQL 8.0常见错误与解决方案
  • 教师与聊天机器人:我走进AI时代课堂的亲身经历
  • 如何在Windows上快速管理多个Node.js版本:nvm-windows终极指南
  • 如何快速配置大气层破解系统:Switch游戏性能优化终极指南
  • 从特征提取到微调:为什么你的BERT在MELD情感分类上效果差?我来帮你诊断
  • mStream播放列表管理技巧:分享、同步与协作功能详解
  • JavaScript-MD5许可证解析:MIT许可证的商业友好性终极指南