• 湖南省2016省赛题。1809: Parenthesis 线段树


    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809

    给定一串平衡的序列,要求交换两个位置之后,问其是否还平衡。

    首先要注意到交换的是两个位置,这两个位置没有大小之分,所以要判断是否swap他们,保持相对大小

    然后如果我们把'('当成是1,把')'当成是-1,那么序列平衡,那么前缀和就是0了。

    然后考虑下交换的时候,如果就交换相同的字符,那么肯定是Yes了,如果是')' 和 '(',那么也是Yes

    因为本来序列就是平衡的,现在这样交换,只不过是把相对位置改了,比如()(),交换2和3,其中和2匹配的1,还是可以看成和交换后的那个字符匹配。

    考虑交换的是'(' 和 ')'

    因为本来在a位置(字符'(')的时候,前缀和是+1了的,那么现在换了个')'过去,所以[a, b - 1]这段区间的前缀和要-2

    [b, lenstr]这段要+2

    当然可以更新后,判断前缀和是否为0,+ 中途不能出现负数。

    然后注意到只有-2那段区间才会产生负数,所以查询[a, b - 1](注意相对大小)的最小值,如果小于2就NO了

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define root 1, n, 1
    #define lson L, mid, cur << 1
    #define rson mid + 1, R, cur << 1 | 1
    int n, q;
    const int maxn = 1e5 + 20;
    int mi[maxn << 2];
    int add[maxn << 2];
    char str[maxn];
    int pre_sum[maxn];
    void pushUp(int cur) {
        mi[cur] = min(mi[cur << 1], mi[cur << 1 | 1]);
    }
    void build(int L, int R, int cur) {
        if (L == R) {
            mi[cur] = pre_sum[L];
            return;
        }
        int mid = (L + R) >> 1;
        build(lson);
        build(rson);
        pushUp(cur);
    }
    int query(int begin, int end, int L, int R, int cur) {
        if (L >= begin && R <= end) { //子图
            return mi[cur];
        }
        int mid = (L + R) >> 1;
        int lans = inf;
        int rans = inf;
        if (begin <= mid) {
            lans = query(begin, end, lson);
        }
        if (end > mid) rans = query(begin, end, rson);
        return min(lans, rans);
    }
    void work() {
        cin >> str + 1;
        for (int i = 1; str[i]; ++i) {
            if (str[i] == '(') {
                pre_sum[i] = pre_sum[i - 1] + 1;
            } else pre_sum[i] = pre_sum[i - 1] - 1;
        }
        build(root);
        for (int i = 1; i <= q; ++i) {
            int a, b;
            cin >> a >> b;
            if (a > b) swap(a, b);
            if (str[a] == str[b] || str[a] == ')' && str[b] == '(') {
                cout << "Yes" << endl;
            } else {
                int MI = query(a, b - 1, root);
    //            cout << MI << endl;
                if (MI < 2) {
                    cout << "No" << endl;
                } else cout << "Yes" << endl;
            }
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        IOS;
        while (cin >> n >> q) work();
        return 0;
    }
    View Code
  • 相关阅读:
    第五次作业之例行报告
    欢迎来怼—第三次Scrum会议
    例行报告
    探路者 Alpha阶段中间产物
    第六次作业—例行报告
    第五次作业—例行报告
    第四次作业—单元测试
    第四次作业—例行报告
    第四次作业—结对编程 四则运算
    第四次作业—1.代码规范
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6041030.html
Copyright © 2020-2023  润新知