• 湖南省第十二届大学生计算机程序设计竞赛 G Parenthesis


    1809: Parenthesis

    Description

    Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions.
    The i-th question is whether P remains balanced after pai and pbi  swapped. Note that questions are individual so that they have no affect on others.
    Parenthesis sequence S is balanced if and only if:
    1. S is empty;
    2. or there exists balanced parenthesis sequence A,B such that S=AB;
    3. or there exists balanced parenthesis sequence S' such that S=(S').

    Input

    The input contains at most 30 sets. For each set:
    The first line contains two integers n,q (2≤n≤105,1≤q≤105).
    The second line contains n characters p1 p2…pn.
    The i-th of the last q lines contains 2 integers ai,bi (1≤ai,bi≤n,ai≠bi).

    Output

    For each question, output "Yes" if P remains balanced, or "No" otherwise.

    Sample Input

    4 2
    (())
    1 3
    2 3
    2 1
    ()
    1 2

    Sample Output

    No
    Yes
    No

    HINT

    题意:

      给你长度n的合法括号匹配和q个询问

      每次询问你 交换ai,bi两个位置的符号,交换后是否还是合法的

    题解:

      分块

      (转化为1,)转化为-1

      合法括号序列满足前缀和永远大于等于0

      利用这个每次修改两个位置

      维护这个关系就好了

      分块可过的

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
     
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
     
    typedef long long LL;
    const long long INF = 1e18;
    const double Pi = acos(-1.0);
    const int N = 2e5+10, M = 1e6+11, mod = 1e6+3, inf = 5000;
     
    int block,n,q,m;
    int sum[N],pos[N],mi[N],a[N],b[N],add[N],f[N];
    char ch[N];
    void init() {
            int s = 0;
            pos[0] = 0;
            memset(b,0,sizeof(b));
            memset(sum,0,sizeof(sum));
            memset(add,0,sizeof(add));
            for(int i = 1; i <= n; ++i) b[i] = a[i];
            for(int i = 1; i <= n; ++i) sum[i] = sum[i-1] + b[i];
            for(int i = 0; i < N; ++i) mi[i] = inf;
            for(int i = 1; i <= n; ++i) {
                if(pos[i] != pos[i-1]) s = 0;
                s += b[i];
                mi[pos[i]] = min(mi[pos[i]],s);
            }
            for(int i = 1; i <= n; ++i) add[pos[i]] += b[i];
            f[0] = 1;
            s = 0;
            for(int i = 1; i <= n; ++i) {
                s+=b[i];
                if(s < 0) f[i] = 0;
                else f[i] = f[i-1];
            }
    }
    int solve(int l,int r) {
            int OK = 1;
            swap(b[l],b[r]);
            if(pos[l] == pos[r]) {
                    int s = sum[block * (pos[l]-1)];
                    for(int i = block * (pos[l]-1) + 1; i <= min(pos[l] * block,n); ++i) {
                        s += b[i];
                        if(s < 0) OK = 0;
                    }
                    for(int i = pos[l]+1; i <= m; ++i) {
                        if(s + mi[i] < 0) OK = 0;
                        s += (add[i]);
                    }if(s < 0) OK = 0;
            } else {
                    int s = sum[block * (pos[l]-1)];
                    for(int i = block*(pos[l]-1) + 1; i <= min(pos[l] * block,n); ++i) {
                        s += b[i];
                        if(s < 0) OK = 0;
                    }
                    for(int i = pos[l]+1; i <= pos[r]-1; ++i) {
                        if(s + mi[i] < 0) OK = 0;
                        s += (add[i]);
                    }
                    for(int i = block * (pos[r]-1) + 1; i <= min(pos[r]*block,n); ++i) {
                        s += b[i];
                        if(s < 0) OK = 0;
                    }
                      for(int i = pos[r]+1; i <= m; ++i) {
                        if(s + mi[i] < 0) OK = 0;
                        s += (add[i]);
                    }
            }
            swap(b[l],b[r]);
            if(OK == 1) return 1;
            else return 0;
    }
    int main() {
            while(scanf("%d%d",&n,&q)!=EOF) {
                scanf("%s",ch);
                block = int(sqrt(n));
                memset(a,0,sizeof(a));
                memset(pos,0,sizeof(pos));
                for(int i = 1; i <= n; i++) {if(ch[i-1] == '(') a[i] = 1; else a[i] = -1; pos[i]=(i-1)/block+1;}
                if(n%block) m = n/block + 1; else m = n/block;
                init();
                for(int i = 1; i <= q; ++i) {
                    int l,r;
                    scanf("%d%d",&l,&r);
                    if(l > r) swap(l,r);
                    if(solve(l,r) == 1) printf("Yes
    ");
                    else printf("No
    ");
                }
            }
            return 0;
    }
     
  • 相关阅读:
    【leetcode】Sum Root to Leaf Numbers(hard)
    【leetcode】First Missing Positive(hard) ☆
    【leetcode】Next Permutation(middle)
    【好玩的应用】QQ连连看辅助工具
    【leetcode】Binary Tree Preorder Traversal (middle)★
    【leetcode】Reverse Words in a String(hard)☆
    【leetcode】Same Tree(easy)
    【leetcode】Factorial Trailing Zeroes(easy)
    【leetcode】Maximum Gap(hard)★
    Behavioral模式之Chain of Responsibility模式
  • 原文地址:https://www.cnblogs.com/zxhl/p/5839024.html
Copyright © 2020-2023  润新知