CF1625E1 Cats on the Upgrade (easy version)

刚刚学完 whk 时无聊看了下提交记录,发现这道富有启发意义的题目。

首先,注意到这实际上就是个序列的 《括号树》,拿来做就行,fi 为以 i 结尾的合法括号串数量,fi=fLi1+1,然后再做一遍前缀和,相减求出以区间 [x,y] 为结尾的数量,但是我们发现会算重,具体的,算重了 [1,x1] 取后缀,[x,y] 取前缀所组合成的合法串数量。

目前题目还有一个性质没用到,就是保证每次询问 [x,y] 合法。那么,显然一定是以 x1 为右端点的合法括号序列与以 x 为左端点的合法括号序列的组合。因为不可能出现一个合法的由这 2 个不合法的组成。若有,显然存在一个 p[x,y] 为右括号,需要匹配 q[1,x1],那么 [x,y] 不合法。

首先 fx1 即后缀合法括号序列,那么还要有 [x,y] 的前缀合法然后相乘才对,于是我们期望找到一个能表示 [x,y] 的前缀合法括号序列。

考虑对于每个前缀合法括号序列,一定是 [x,p],那么因为 [x,y] 合法,显然 [p+1,y] 也合法。

于是,每个前缀合法括号序列都存在唯一一个以 y 为结尾,开头在 [x,y] 的合法括号序列与之对应。(双射)

于是,我们现在期望通过 f 求后者。

发现倘若以 y 为右端点,但左端点在 [1,x1] 的合法括号序列,它一定可以划分为 s:[p,x1]+[x,y]。否则,若左端点在 [x,y] 则一定无法划分,即不会计入 fx1,但 2 部分都会计入 fy

综上,减去 fx1(fyfx1)

#include <bits/stdc++.h> #define int long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } const int N=(int)(3e5+5); char s[N]; int n,m,f[N],st[N],sum[N],top; signed main() { n=rd(); m=rd(); scanf("%s",s+1); for(int i=1;i<=n;i++) { if(s[i]=='(') st[++top]=i; else { if(!top) continue ; f[i]=f[st[top]-1]+1; --top; } } for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+f[i]; // printf("%d ",f[i]); } while(m--) { rd(); int x=rd(),y=rd(); printf("%lld\n",sum[y]-sum[x-1]-f[x-1]*(f[y]-f[x-1])); // [1,x-1]*[x,y] ,[x,y]=[y,x] } return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16599775.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2021-08-18 loj#502. 「LibreOJ β Round」ZQC 的截图
2021-08-18 CF799F Beautiful fountains rows
点击右上角即可分享
微信分享提示