zoukankan      html  css  js  c++  java
  • 【Codeforces Round #223 (Div. 1) C】Sereja and Brackets

    题目链接

    链接

    翻译

    给你一个区间,让你输出其中合法的括号序列(不要求连续)的最长的长度。

    题解

    线段树

    在节点上维护当前这个区间内左右括号已经匹配了的对数 (mb[rt])

    另外维护两个用于合并的数组 (lb[rt]) 表示还没有用来匹配的左括号的数目,(rb[rt]) 则是右括号。

    (trick) 就是,在合并的时候因为区间已经足够小了。两个子区间不考虑有匹配的情况了,现在只要考虑

    左括号在左区间然后右括号在右区间的情况即可。

    询问的时候也要做类似的合并操作,并且要记录两个询问的子区间对应的 (lb[rt])(rb[rt])(得重新算)。

    代码

    #include <bits/stdc++.h>
    #define lson l,mid,rt*2
    #define rson mid+1,r,rt*2+1
    #define LL long long
    using namespace std;
    
    const int N = 1e6;
    
    char s[N+10];
    int m,lb[N*4+10],rb[N*4+10],mb[N*4+10];
    
    void build(int l,int r,int rt){
        if (l == r){
            if (s[l] == '('){
                lb[rt] = 1;
            }else{
                rb[rt] = 1;
            }
            return;
        }
        int mid = (l+r)/2;
        build(lson);build(rson);
        mb[rt] = mb[rt*2] + mb[rt*2+1];
        int t = min(lb[rt*2],rb[rt*2+1]);
        mb[rt] = mb[rt] + t;
        lb[rt] = lb[rt*2] + lb[rt*2+1] - t;
        rb[rt] = rb[rt*2] + rb[rt*2+1] - t;
    }
    
    int _query(int L,int R,int l,int r,int rt,int &lbRest,int &rbRest){
        if (L<=l && r <= R){
            lbRest = lb[rt];rbRest = rb[rt];
            return mb[rt];
        }
        int mid = (l+r)/2;
        if (mid<L){
            return _query(L,R,rson,lbRest,rbRest);
        }else if (R<=mid){
            return _query(L,R,lson,lbRest,rbRest);
        }else{
            int tlbRest,trbRest;
            int t1 = _query(L,mid,lson,lbRest,rbRest);
            int t2 = _query(mid+1,R,rson,tlbRest,trbRest);
            int t = min(lbRest,trbRest);
            lbRest = lbRest + tlbRest - t;
            rbRest = rbRest + trbRest - t;
            return t1 + t2 + t;
        }
    }
    
    int main(){
        // freopen("C://1.cppSourceProgram//rush.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0);
        cin >> (s+1);
        int n = strlen(s+1);
        build(1,n,1);
        cin >> m;
        while (m--){
            int l, r;
            cin >> l >> r;
            int xx1,xx2;
            cout << _query(l,r,1,n,1,xx1,xx2)*2 << endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    几个前端时间插件总结
    微信支付——退款篇
    getTime()方法在苹果系统的bug
    【转载】[JS]让表单提交返回后保持在原来提交的位置上
    【转载】 IE/Firefox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法
    webstorm相关设置
    检测无标题的
    数组去重的方法
    Git 版本比较
    Git 回到过去
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14179981.html
Copyright © 2011-2022 走看看