【无码专区7】括号序列(思维)

因为只有std,没有自我实现,所以是无码专区

主要是为了训练思维能力

solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dls的实现不太一样。

std可能也会带有博主自己的注释。


problem

给定一个由左右括号构成的字符串 sss,对于每一个位置 iii,定义 ansi:ans_i:ansi: 有多少个子串满足这个子串是一个合法的括号序列,并且 iii 这个位置在子串中。

合法的括号序列定义:

  • 空串合法。
  • 如果 SSS 合法,那么 (S)(S)(S) 也是合法的。
  • 如果 S,TS,TS,T 合法,那么 STSTST 也是合法的。

由于答案很大,输出 ∑i=1∣S∣(i⋅ansimod109+7)\sum_{i=1}^{|S|}\Big(i·ans_i\mod{10^9+7}\Big)i=1S(iansimod109+7),注意是先取模再相加,相加后并不需要取模。

∣S∣≤107,1s,512MB|S|\le 10^7,1s,512MBS107,1s,512MB


my idea

套路的,将括号序列转化为 ±1±1±1 分数序列,左括号为 +1+1+1,右括号为 −1-11。并求前缀和

当一个串为合法括号序列,当且仅当每个位置的前缀和都不小于 000 ,且最后一个位置的前缀和恰好为 000

保证了没有中途右括号个数多于左括号个数,以及最后左右括号个数匹配,显然这是充要条件。

考虑枚举合法括号序列的左端点。

可以肯定的是,被枚举的位置 iii 本身首先得是个 (

通过某种手段快速找到 iii 后面的第一个小于 000 的前缀和位置 jjj。因为从 jjj 开始后面就一定不合法了。

注意以下的前缀和若无特殊说明,都是指以 iii 开始的前缀和,所以应该满足 sumj−sumi−1<0sum_j-sum_{i-1}<0sumjsumi1<0

显然,jjj 位置一定是个 ),且 [i,j)[i,j)[i,j) 一定是一个合法括号序列。当然这个性质没有什么用。有用的只是 jjj 的位置。

特殊地,如果一直到最后 ∣S∣|S|S 都没找到,就返回 ∣S∣+1|S|+1S+1 即可。

考虑二分,但很容易发现这并不具有连续性,错误。

考虑线段树,相当于在 iii 时去考虑小于 sumi−1sum_{i-1}sumi1sumjsum_jsumj

具体而言:

从后往前做,到 iii 时线段树上储存的是 [i,n][i,n][i,n] 的前缀和(此前缀和是指从 111 开始的)。

线段树是权值线段树,每个叶子权值储存的是距离 iii 最近的下标 jjj

所以查询就是在线段树上 [1,sumi−1)[1,sum_{i-1})[1,sumi1) 区间查询最小的节点权值。

即以权值为线段树上的下标,以下标为线段树上的权值。

维护区间最小值。

修改:每次 iii 前移 −1-11,就把 iii 的前缀和对应的线段树上叶子节点权值更改为 iii

确定了整个大区间,考虑其中的的合法序列,即 s[i,k],i<k<js[i,k],i<k<js[i,k],i<k<j 的合法括号序列。

显然只需要满足 kkk 的前缀和为 000 即可。

现在的问题是怎么迅速找到这些 kkk,并快速计算贡献。

先考虑快速计算贡献,显然 [i,k][i,k][i,k] 一段合法括号序列会让 i≤x≤ki\le x\le kixkansxans_xansx+1+1+1

所以这里采取差分手段,对 ansk+1,ansi−1−1ans_k+1,ans_{i-1}-1ansk+1,ansi11,最后的时候来一次后缀和,每个 ansxans_xansx 都是正确的了。

最后就只剩下迅速找到这些 kkk 的问题了。

一开始就将所有的前缀和 sumisum_isumi(这里的前缀和是指以 111 开始的)桶排序。

即以 sumisum_isumi 为桶下标分装所有的前缀和,用 vector 存储,桶内放的是前缀和下标。

然后从前往后考虑左端点 iii,找到 sumisum_isumi 的那个桶,以 jjj 为分解线二分出最大的小于 jjj 的位置 ppp,然后桶内前 ppp 个的点对应的 ansansans 都可以差分 +1+1+1

显然也不能枚举 1∼p1\sim p1p 一个一个加,所以在桶里面也进行前缀和差分,在 111 位置 +1+1+1,在 p+1p+1p+1 位置 −1-11

每次在二分之前,都得先在 sumisum_isumi 的桶内把第一个元素丢出去,在丢之前又得把差分数组及时传递。

所以在 iii 时,所有桶内都只有 i+1∼∣S∣i+1\sim |S|i+1S 的前缀和(这里的前缀和是指 111 开始的),并且桶内的差分是更新过的,

意思就是如果要扔去某个桶的对头 xxx(桶内存的是下标),对头下一个是 yyy,那么差分数组更新一下 ansy+=ansxans_y+=ans_xansy+=ansx

因为第二个部分的桶是从前往后做,第一个部分是从后往前做,顺序不同所以要分开做。

桶内前缀差分,差分完后,桶外后缀差分。

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

只能通过 70%70\%70% 的数据点 ∣S∣≤106|S|\le 10^6S106


solution

凸(艹皿艹 ) O(nlog⁡n)O(n\log n)O(nlogn) 尼玛思维代码量比 O(n)O(n)O(n) 还难。

首先处理一下哪些括号是匹配的,用栈来做。

w(X()X(Z()Z)X(Y()Y()Y)X()X)W ,把括号之间的间隔标号,对于一堆匹配的括号,即合法括号序列,要求两端的标号相同。

第一次见这种处理,是小生孤陋寡闻了Orzqwqqwq

问题转化为,有若干个标号,要统计位置 iii 两端有多少对标号是相同的。

dls题解就给个思路,还是得自己仔细想具体代码算法实现。qwq

对于每个匹配括号 ()()(),对于左括号 iii ,记录一个 upiup_iupiupiup_iupi 是最小的能包含这对匹配括号的另一对匹配括号的左括号位置。

(..(..)...),第一个左括号就是 upiup_iupi,这期间要保证不存在 upi<x<i,match(i)<y<match(upi),x,yup_i<x<i,match(i)<y<match(up_i),x,yupi<x<i,match(i)<y<match(upi),x,y 能匹配。

类似前缀和差分,ansupi→ansians_{up_i}\rightarrow ans_iansupiansi

ai,bi:a_i,b_i:ai,bi: 记录左右的连续可完美匹配的括号。

(..()..)(..)(..) 第三个左括号和第三个右括号假设是现在 iii 对应的匹配,那么可以选择第一个左括号到第三个右括号,第一个左括号到第四个右括号。

这就用 ai∗bmatch(i)a_i*b_{match(i)}aibmatch(i) 来统计,具体实现可以看 std。

时间复杂度: O(n)O(n)O(n)


std

#include <bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);using namespace std;const int N = 1e7 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);template<class T, class S> inline void add(T &a, S b) {a += b;if (a >= mod)a -= mod;
}template<class T, class S> inline void sub(T &a, S b) {a -= b;if (a < 0)a += mod;
}template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;
}template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;
}mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());int n;
int stk[N], top;
int match[N], a[N], b[N], up[N];
int ans[N];
char s[N];int main() {freopen("bracket.in", "r", stdin);freopen("bracket.out", "w", stdout);scanf("%s", s + 1);n = strlen(s + 1);top = 0;for (int i = 1; i <= n; i++) {if (s[i] == '(') { //左右括号匹配 up[i]:i位置前最靠近i的还未匹配的左括号/*因为up[i]是还未匹配的,所以up[i]匹配的右括号一定是包含i的(如果能匹配的话)即长相为 (..(..)...) */up[i] = stk[top];stk[++top] = i;} else if (top) {match[i] = stk[top];match[stk[top]] = i;top--;}}for (int i = 1; i <= n; i++) {if (!match[i] || s[i] == '(')continue;b[i] = b[match[i] - 1] + 1; //b[i]标号右括号 b[i]:i位置右括号的标记应为匹配的左括号前一个位置的标号+1}for (int i = n; i >= 1; i--) {if (!match[i] || s[i] == ')')continue;a[i] = a[match[i] + 1] + 1;//a[i]标号左括号 a[i]:i位置左括号的标记应为匹配的右括号后一个位置的标号+1}
//+1表示只选i-j这对匹配括号for (int i = 1; i <= n; i++) {if (!match[i] || s[i] == ')')continue;ans[i] = 1LL * a[i] * b[match[i]] % mod;if (up[i])add(ans[i], ans[up[i]]);ans[match[i]] = ans[i];}LL ret = 0;for (int i = 1; i <= n; i++) {ret += 1LL * ans[i] * i % mod;}printf("%lld\n", ret);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2016ICPC青岛

2016ICPC青岛 题号题目难度知识点ARelic Discovery签到贪心BPocket Cube快铜大模拟CPocky签到数论&#xff0c;推公式DLucky CoinsEFibonacciFLambda CalculusGCoding Contest银牌题网络流HPatternITravel BrochureJCliquesKFinding HotelsLTower AttackMGenerator and Monito…

ML.NET 发布0.11版本:.NET中的机器学习,为TensorFlow和ONNX添加了新功能

微软发布了其最新版本的机器学习框架&#xff1a;ML.NET 0.11带来了新功能和突破性变化。新版本的机器学习开源框架为TensorFlow和ONNX添加了新功能&#xff0c;但也包括一些重大变化, 这也是发布RC版本之前的最后一个预览版&#xff0c;这个月底将发布0.12版本&#xff0c;也就…

CF1267G Game Relics(期望、背包)

解析 有些遗憾的一个题。 几乎已经做出来了&#xff0c;但最后把买的代价看成平均数确实没有想到。 还有那个背包我觉得直接做会炸精度&#xff0c;就开始各种玩泥巴。 悲。 比较显然的结论是最优解必然是先抽抽抽然后再买买买。 剩 i 个宝物的时候抽出一个新宝物的期望代价比…

铺地毯(矩形的交+前后缀矩形交)

铺地毯problemsolutioncodeproblem 给定矩阵的长宽 P,QP,QP,Q&#xff0c;矩阵从下往上从左往后编号增加&#xff0c;(0,0)∼(P,Q)(0,0)\sim (P,Q)(0,0)∼(P,Q)。 给定 nnn 张长宽平行于坐标轴的矩形地毯&#xff0c;左下角和右上角的坐标。 求被至少 n−1n-1n−1 张地毯覆盖…

AT2366 [AGC012F] Prefix Median(dp)

解析 确实精妙的一道题。 卡在最后一步dp转化上了&#xff0c;这个转化也确实是本题的难点。 当一个计数难以下手的时候&#xff0c;先想想如何判合法&#xff1f; 不难想到一个较为显然的贪心&#xff1a;假如和上一个一样&#xff0c;就填一个当前的最大值和最小值&#xf…

2020CCPC长春

2020CCPC长春 题号题目难度知识点AKrypton签到01背包BThe Tortoise and the HareCQuantum GeometryDMeaningless Sequence签到推公式EDefense of Valor LeagueFStrange Memory树上启发式合并GMonkey’s KeyboardHCombination LockIKawaii CourierJAbstract PaintingKRagdollLC…

如何使用AWS和Azure的配置存储服务保存读取配置

原文&#xff1a;Want to yank configuration values from your .NET Core apps? 作者&#xff1a;pauljwheeler译文&#xff1a;https://www.cnblogs.com/lwqlun/p/10508748.html译者&#xff1a;Lamond Lu示例源代码&#xff1a;https://github.com/lamondlu/LoadConfigurat…

基站建设(三元环计数+根号分治 / bitset)

基站建设problemsolutioncodeproblem 给定 nnn 个地点&#xff0c;以及每个地点的可靠度 RiR_iRi​。 有 mmm 条光纤架&#xff0c;每一条连接两个不同的地点&#xff0c;且是双向的。 测试基站由 444 个信号塔&#xff0c;有 222 个主信号塔和 222 个副信号塔。 要求主信号…

CF1060F Shrinking Tree(期望、树形dp)

解析 神题。 把每个节点提到根 rt 单独考虑。 设 dpi,jdp_{i,j}dpi,j​ 表示当 rt 进入 i 时子树内还有 j 条边未合并的方案的期望之和&#xff0c;gi,jg_{i,j}gi,j​ 表示当 rt 进入 i 的父亲时 i 的子树内&#xff08;包括连向父亲的边&#xff09;还有 j 条边未合并的方案…

Meaningless Sequence Gym - 102832D

Meaningless Sequence Gym - 102832D 题意&#xff1a; 给你n和c&#xff0c;an的公式如下图 让你求a0…an的和&#xff0c;mod 1e97 题解&#xff1a; 训练时推了好一阵子才和队友推出 我看网上正解为&#xff1a; 一个数的大小与它的二进制表示中的1的个数有关 ac(二进制…

【.NET Core项目实战-统一认证平台】第十六章 网关篇-Ocelot集成RPC服务

一、什么是RPCRPC是“远程调用&#xff08;Remote Procedure Call&#xff09;”的一个名称的缩写&#xff0c;并不是任何规范化的协议&#xff0c;也不是大众都认知的协议标准&#xff0c;我们更多时候使用时都是创建的自定义化&#xff08;例如Socket&#xff0c;Netty&#…

【学习笔记】无向图、有向图的三元环、四元环计数问题(根号分支+bitset)

三元环计数和四元环计数问题无向图三元环计数问题根号分治bitset无向图四元环计数问题有向图三四元环计数问题无向图三元环计数问题 根号分治 记 di:id_i:idi​:i 在原图中的度数。 按照以下规则改写无向图为有向图&#xff1a; 对于一条边 u,vu,vu,v。 如果两点度数不同&a…

.net Core2.2 WebApi通过OAuth2.0实现微信登录

前言微信相关配置请参考 微信公众平台 的这篇文章。注意授权回调域名一定要修改正确。微信网页授权是通过OAuth2.0机制实现的&#xff0c;所以我们可以使用 https://github.com/china-live/QQConnect 这个开源项目提供的中间件来实现微信第三方登录的流程。开发流程1、新建一个…

Nginx优化(重点)与防盗链(新版)

Nginx优化(重点)与防盗链 Nginx优化(重点)与防盗链一、隐藏Nginx版本号1、修改配置文件2、修改源代码 二、修改Nginx用户与组1、编译安装时指定用户与组2、修改配置文件指定用户与组 三、配置Nginx网页的缓存时间四、实现Nginx的日志切割1、data的用法2、编写脚本进行日志切割的…

Almost Sorted Array HDU - 5532

Almost Sorted Array HDU - 5532 题意&#xff1a; 如果一个数组的元素“按非递减或非递增顺序排列”&#xff0c;那么称这个数组有序。现在&#xff0c;LYD给了你一个数组a&#xff0c;他让你从中选择并移除仅仅1个元素&#xff0c;请问剩下的元素构成的数组有可能是有序的吗…

CF906D:Power Tower(拓展欧拉定理、暴力)

解析 大降智题。 受相逢是问候的影响&#xff0c;第一眼直接线段树&#xff0c;写完WA完才发现这个玩意没有结合律。 然后开始用 xyz(xy)yz−1x^{y^z}(x^y)^{y^{z-1}}xyz(xy)yz−1 这样的东西嗯做&#xff0c;结果只是在玩泥巴。 lemma&#xff1a;迭代求 φ\varphiφ 的次数是…

CodeForces730E Award Ceremony(拓扑排序+结论)

CF730E. Award Ceremonyproblemsolutioncodeproblem 题目链接 题目大意&#xff1a; 给出 nnn 个队封榜时的榜单 aia_iai​ 和揭榜时的变化情况 did_idi​。 揭榜时&#xff0c;这个队的名次会变化 tit_iti​。 注意在别的队揭榜时&#xff0c;自己队的排名也是动态变化的…

.Netcore 2.0 Ocelot Api网关教程(番外篇)- Ocelot v13.x升级

由于Ocelot系列博客好久没更新&#xff08;差不多有10个月的时间了&#xff09;&#xff0c;在此先说声抱歉&#xff0c;Ocelot系列会继续更新下去。在写上一篇配置管理的时候发现官方文档已经和以前的不一样&#xff0c;而Ocelot也从5.0版本更新到了13.x版本&#xff0c;进行了…

CF765F Souvenirs(暴力、线段树)

解析 比较神奇的一道题。 考虑一个常规套路&#xff1a;把询问离线&#xff0c;移动右端点&#xff0c;维护左端点答案。 考虑暴力维护&#xff0c;对于当前的 aixa_ixai​x&#xff0c;左侧如图所示的这两条线上的点都可以产生新的可能答案。 容易构造使得单次产生的新点是…

Hard Disk Drive HDU - 4788

Hard Disk Drive HDU - 4788 题意&#xff1a; 通常制造商认为1“kilo”等于1000&#xff0c;但操作系统会认为是1024。 因此&#xff0c;当你购买了一个100MB的硬盘&#xff0c;电脑却只显示大约有95MB&#xff0c;这缺失了大约5MB。 对于硬盘的大小&#xff0c;有多种单位描…