数据结构大师(求区间最长合法括号子序列)

数据结构大师

时间限制: 1 Sec 内存限制: 128 MB

题目描述

小$Z$是个数据结构高手,这天他得到了一个由左括号和右括号组成的字符串。随之而来的是 \(m\) 次询问,对于第 \(i\) 次询问,小Z需要回答出这个字符串的第$l_i$ 到$r_i$ 个字符组成的字串中最长的合法括号子序列的长度。
小$Z$认为一个由左右括号组成的序列$A$合法,当且仅当其满足至少一个以下条件。
$A$为空。

  • $A=(B)$其中$B$是一个合法的括号序列。
  • \(A=BC\),其中$BC$都是合法的括号序列。
  • 比如合法的括号序列有$(),()(),(())$等。

输入

第一行读入两个数字$n,m$,分别表示长度和询问次数,接下来一行读入字符串$S$。
最后m行每行读入两个数$l_i,r_i$,表示这次询问的区间。

输出

对于每个询问输出一行表示答案。
样例输入
4 1
(())
2 4
样例输出
2
提示
对于$30%$的数据,满足$n,m<=500$。
对于$60%$的数据,满足$n,m<=5000$。
对于$100%$的数据,满足$1≤n≤106,1≤m≤105$。

思路:

想到是区间问题自然想到了线段树,由于子序列不连续,我们用线段树维护‘(‘和‘)‘的数量记为$l,r$。
那么合并$ls$和$rs$新增匹配$min(l,r)$,设为$x$,(若记$mx$为区间最长匹配对数)也即$t[p].mx+=x$;
同时我们累和$ls,rs$的长度,最终$t[p].mx=t[ls].mx+t[rs].mx+x$;
对$l,r$的维护显然,减去已经匹配成功的即可;

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int N=1e6+5;
const ll mod=1e9+7;
const double eps=1e-5;
//const double pi=acos(-1);

#define ls p<<1
#define rs p<<1|1

char s[N];
struct seg
{
    int l,r,mx;
}t[N<<2];
void build(int p,int l,int r)
{
    if(l==r)
    {
        t[p].l=s[l]==‘(‘;
        t[p].r=s[l]==‘)‘;
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    int x=min(t[ls].l,t[rs].r);
    t[p].mx=t[ls].mx+x+t[rs].mx;
    t[p].l=t[ls].l-x+t[rs].l;
    t[p].r=t[ls].r+t[rs].r-x;
}
seg ask(int p,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
        return t[p];
    int mid=l+r>>1;
    if(y<=mid)
        return ask(ls,l,mid,x,y);
    else if(x>mid)
        return ask(rs,mid+1,r,x,y);
    else
    {
        seg ans;
        seg lx=ask(ls,l,mid,x,y);
        seg rx=ask(rs,mid+1,r,x,y);
        int use=min(lx.l,rx.r);
        ans.mx=lx.mx+rx.mx+use;
        ans.l=lx.l+rx.l-use;
        ans.r=lx.r+rx.r-use;
        return ans;
    }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin>>n>>m;
    cin>>(s+1);
    build(1,1,n);
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        printf("%d\n",ask(1,1,n,l,r).mx*2);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Suiyue-Li/p/12665036.html

时间: 2024-08-29 20:33:05

数据结构大师(求区间最长合法括号子序列)的相关文章

九度oj 题目1342:寻找最长合法括号序列II

题目描述: 假如给你一个由’(‘和’)’组成的一个随机的括号序列,当然,这个括号序列肯定不能保证是左右括号匹配的,所以给你的任务便是去掉其中的一些括号,使得剩下的括号序列能够左右括号匹配且长度最长,即最长的合法括号序列. 输入: 测试数据包括多个,每个测试数据只有一行,即一个随机的括号序列,该括号序列的长度保证不超过106. 输出: 对于每个测试案例,输出一个整数,表示最后剩下的最长合法括号序列长度. 样例输入: (())() (() 样例输出: 6 2 这个题和1337求的是不一样的代码如下

九度oj 题目1337:寻找最长合法括号序列

题目描述: 给你一个长度为N的,由’(‘和’)’组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的含义便是,在这个序列中,所有的左括号都有唯一的右括号匹配:所有的右括号都有唯一的左括号匹配.例如:((()))()()便是一个长度为10的合法括号序列,而(()))( 则不是. 需要你求解的是,找出最长的合法括号子序列的长度,同时找出具有这样长度的序列个数. 输入: 测试数据包括多个,每个测试数据包含两行: 第一行为一个整数N,其中N不会超过10^6. 第二行为一个长度为N的字

[Jobdu] 题目1337:寻找最长合法括号序列

题目描述: 给你一个长度为N的,由’(‘和’)’组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的含义便是,在这个序列中,所有的左括号都有唯一的右括号匹配:所有的右括号都有唯一的左括号匹配.例如:((()))()()便是一个长度为10的合法括号序列,而(()))( 则不是. 需要你求解的是,找出最长的合法括号子序列的长度,同时找出具有这样长度的序列个数. 输入: 测试数据包括多个,每个测试数据包含两行: 第一行为一个整数N,其中N不会超过10^6. 第二行为一个长度为N的字

LongestValidParentheses, 求最长合法括号子串长度-----同类问题ValidParentheses,GenerateParentheses

问题描述:求括号字符串中最长合法子串长度.例如:()((),返回2,而不是4. 算法分析:还是利用栈,和判断合法括号对是一样的. 1 public static int longestValidParentheses(String s) { 2 Stack<int[]> stack = new Stack<int[]>(); 3 int result = 0; 4 5 for(int i=0; i<=s.length()-1; i++) 6 { 7 char c = s.ch

[leetcode]32. Longest Valid Parentheses最长合法括号子串

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. Example 1: Input: "(()" Output: 2 Explanation: The longest valid parentheses substring is "()" Example

1478 括号序列的最长合法子段

1478 括号序列的最长合法子段 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 这里有另一个关于处理合法的括号序列的问题. 如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的.例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(

求最长有效括号长度 java

题目:输入只包含圆括号的字符串,找出最长的合法括号子串的长度 比如: "(()"-->2,最长的有效子串是"()" ")()())"-->4,最长的有效子串是"()()" 解题思路: 如果输入是左括号就直接入栈,如果是右括号,如果此时栈为空或此时的栈顶不为左括号就不作处理同时把记录有效长度的临时变量置为0,如果栈顶为左括号则出栈并把记录有效长度的临时变量加2.最后返回最大的记录长度的临时变量即可. 代码: impo

[LeetCode] Longest Valid Parentheses 最长有效括号

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. For "(()", the longest valid parentheses substring is "()", which has length = 2. Another example is &

HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)

Problem Description Now you are back,and have a task to do: Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s. And you have some query,each time you should calculate f(s[l...r]), s[l