zoukankan      html  css  js  c++  java
  • 数据结构大师

    数据结构大师

    时间限制: 1 Sec 内存限制: 128 MB
    [提交] [状态]

    题目描述

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

    输入

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

    输出

    对于每个询问输出一行表示答案。

    样例输入 Copy

    4 1
    (())
    2 4

    样例输出 Copy

    2

    提示

    对于30%的数据,满足n,m<=500。
    对于60%的数据,满足n,m<=5000。
    对于100%的数据,满足1≤n≤(10^6),1≤m≤(10^5)

    思路

    想到是区间问题自然想到了线段树,由于子序列不连续,我们用线段树维护'('和')'的数量记为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的维护显然,减去已经匹配成功的即可;

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    char s[maxn];
    #define ls (rt<<1)
    #define rs ((rt<<1)+1)
    int n,m;
    struct node {
        node() {};
    
        node(int l, int r, int mx) : l(l), r(r), mx(mx) {};
        int l, r, mx;
    }t[maxn<<2];
    void build(int rt,int l,int r) {
        if (l == r) {
            t[rt].l = s[l] == '(';
            t[rt].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[rt].mx = t[ls].mx + x + t[rs].mx;
        t[rt].l = t[ls].l - x + t[rs].l;
        t[rt].r = t[ls].r + t[rs].r - x;
    }
    node ask(int rt,int l,int r,int x,int y) {
        if (x <= l && r <= y)
            return t[rt];
        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 {
            node lx = ask(ls, l, mid, x, y);
            node rx = ask(rs, mid + 1, r, x, y);
            int use = min(lx.l, rx.r);
            return node(lx.l + rx.l - use, lx.r + rx.r - use, lx.mx + rx.mx + use);
        }
    }
    int main() {
        scanf("%d%d", &n, &m);
        scanf("%s", s + 1);
        build(1, 1, n);
        while (m--) {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d
    ", ask(1, 1, n, l, r).mx * 2);
        }
        return 0;
    }
    
  • 相关阅读:
    sqlserver 时间格式函数详细
    asp.net中session的原理及应用
    asp.net中的cookie
    WCF 应用(一)
    c#操作word文档之简历导出
    浅解多线程
    .net反射详解
    正则表达式、常用的匹配总结
    存储过程详解
    jquery.pagination.js分页
  • 原文地址:https://www.cnblogs.com/Accpted/p/12689195.html
Copyright © 2011-2022 走看看