首页 > 其他分享 >[CF380C] Sereja and Brackets 题解

[CF380C] Sereja and Brackets 题解

时间:2023-01-29 00:34:15浏览次数:45  
标签:le Brackets int 题解 Sereja 区间 括号 minp

[CF380C] Sereja and Brackets 题解

给定一个括号串 \(s\) 与 \(m\) 次询问。

  • l, r 回答字符串 \(t = s_ls_{l+1}\dots s_r\)​ 的所有子序列中最长的合法括号串的长度。

\(1\le |s|\le 10^6\),\(1\le m\le 10^5\)

想法

对于括号序列有一种数形结合的 trick,即把 ( 记为 1) 记为 -1,并记录它们的前缀和。

例如样例可以转换为 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1

它的前缀和为 1 0 -1 0 1 0 -1 0 1 0 -1 0

把它拍到折线统计图上

记 \(h_i\) 为 \(i\) 的前缀和。

观察发现一个合法括号序列区间 [l, r] 一定满足:

  1. \(\forall i\in[l, r], h_i \geq h_l\),即 \(l\) 是区间的最低点。
  2. \(h_r = h_l\),即区间的结尾一定与区间的开头高度相等。

于是只需要统计区间内这些区间的长度即可,不妨反向考虑整个问题。

设区间长度为 \(len\),最低点高度为 \(minp\)。

则区间中未匹配的左括号数量为:\(|h_l - minp|\);

区间中未匹配的右括号数量为:\(|h_r - minp|\)

因此答案为 \(len - |h_l - minp| - |h_r - minp|\)。

只需要求出 \(minp\) 整个问题就解决了。

可以用线段树 / ST表解决这个 RMQ 问题。

实现

我采用了线段树,时间复杂度:\(O(m\log n)\)

代码实现中需要一些边界判断。

// Problem: Sereja and Brackets
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF380C
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// Author: Moyou
// Copyright (c) 2022 Moyou All rights reserved.
// Date: 2023-01-28 22:36:03

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#define speedup (ios::sync_with_stdio(0), cin.tie(0), cout.tie(0))
#define INF 0x3f3f3f3f
using namespace std;

const int N = 1e6 + 10;

int h[N];

void init(string s)
{
    for (int i = 0; i < s.size(); i++)
        h[i] = (i - 1 >= 0 ? h[i - 1] : 0) + (s[i] == '(' ? 1 : -1);
    for(int i = s.size(); i; i --)
        h[i] = h[i - 1];
    h[0] = 0;
}

int n;
string s;

struct owo
{
    int l, r, dat;
} tr[N << 2];

void build(int k, int l, int r)
{
    tr[k].l = l, tr[k].r = r;
    if (l == r)
        tr[k].dat = h[l];
    else
    {
        int mid = l + r >> 1;
        build(k << 1, l, mid);
        build(k << 1 | 1, mid + 1, r);
        tr[k].dat = min(tr[k << 1].dat, tr[k << 1 | 1].dat);
    }
}

int query(int k, int ql, int qr)
{
    int l = tr[k].l, r = tr[k].r, mid = l + r >> 1;
    if (ql <= l && qr >= r)
        return tr[k].dat;
    int t = INF;
    if (ql <= mid)
        t = query(k << 1, ql, qr);
    if (qr > mid)
        t = min(t, query(k << 1 | 1, ql, qr));
    return t;
}

int main()
{
    speedup;
    cin >> s >> n;
    init(s), build(1, 1, s.size());

    for (int i = 1; i <= n; i++)
    {
        int l, r;
        cin >> l >> r;
        int len = r - l + 1;
        int minp = query(1, l, r);
            int a = abs(h[l - 1] - minp), b = abs(h[r] - minp);
        cout << len - a - b << endl;
    }

    return 0;
}

标签:le,Brackets,int,题解,Sereja,区间,括号,minp
From: https://www.cnblogs.com/MoyouSayuki/p/17071573.html

相关文章

  • 【题解】[ABC286C] Rotate and Palindrome 题解
    更好的阅读体验洛谷题目传送门|AT原题传送门思路观察题目可以发现A操作最多只能执行\(n\)次,超过以后字符串又会回到初始状态。首先考虑A操作如何实现,一种办法......
  • 【题解】[IOI2018] werewolf 狼人
    题目分析这个题本身很简单,可能就是因为是IOI题所以看上去就难了些吧。其实题目就是让我们先走一段全部大于等于\(l\)的点然后再走一段全部小于等于\(r\)的点,那么能......
  • xhost: unable to open display ""问题解决
    一、需求xhost可是增强vnc的图形界面显示二、问题解决设置一下dispaly  通过执行exportDISPLAY=x.x.x.x:1,x.x.x.x指的是虚拟机ip地址,DISPLAY用来设置将图形显示......
  • 视频美颜sdk疑难问题解答
    目前,美颜sdk已经成了大多数直播、视频平台的刚需,因为这是用户需求,同样也是市场的风向。随着需求量的暴增,视频美颜sdk一些技术向的提问也多了起来,今天小编就为大家讲解一下视......
  • # CF#847 (Div. 3)ABCDE题解
    CodeforcesRound#847(DFiv.3)APolycarpandtheDayofPiProblem-A-Codeforces题目描述OnMarch14,thedayofthenumber$\pi$iscelebratedallov......
  • 【题解】洛谷-P5643 [PKUWC2018]随机游走
    用到了概率期望的很多技巧。首先要求的是走遍集合中所有节点步数的期望,也就是步数最大值的期望,根据\(\text{min-max}\)容斥,有:\[E\left(\max_{i\inS}x_i\right)=\sum_......
  • 题解 CF1670F【Jee, You See?】
    problem给出常数\(n,z\),令\(F(m)\)表示所有满足以下条件的数列\(\{a_i\}\)的数量:\(\{a_i\}\)有\(n\)项,都是非负整数。它们的和不大于\(m\)。它们的异或和恰......
  • 【ElementPlus】el-menu侧边垂直菜单折叠后图标会消失的问题解决
    首先上代码<template><templatev-for="subIteminmenuList":key="subItem.path"><!--有子菜单--><el-sub-menuv-if="subItem.children&&s......
  • CF908G 题解
    题意传送门给\(x\le10^{700}\),问\(1\)到\(x\)中每个数在各数位排序后得到的数的和。答案模\(10^9+7\)。题解学到一种新鲜的转化方式,来记一下。将\(x\)的位数......
  • Codeforces 708 A-E1题解
    A.Meximization这道题问给一些数,如何让前缀的mex之和最大,那么首先,我们要抬mex的话肯定是要把前面都铺垫完的,所以在i位置确定的时候,i+1自然是越大越好,可以证明i+1的位......