Bracket Matching RMQ/Violence

Keywords: less

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

Significance: Give a matched parentheses sequence, swap the parentheses of two positions arbitrarily, judge whether they match, if the matched output Yes does not match the output No.

A Method of Judging Matching of Brackets

   int sum=0;
   for ( int i = 0; i < n; i++ ) {
                    if ( s[i] == '(' ) sum++;  // Meeting'('sum+1)
                    else sum--;    // Meet')'sum-1
                    if ( sum < 0 ) break;  // If sum < 0, parentheses do not match
   }

Analytical reference: http://blog.csdn.net/bcwan_/article/details/52436229

Analysis: 1. When the character on the left is the same as the character on the right, the exchange must be a bracket balance string. 

      2. When the character on the left is')', the exchange must be a balanced string in parentheses. 
      If the character on the left')'is exchanged with the character on the right ('), then the two exchanged at this time must match into a pair. 
      If the character on the left')'is exchanged with the character on the right')', then the two characters exchanged are the same at this time, satisfying 1. 

      3. When the character on the left is'('), the number of unsatisfactory characters is related to the number of unmatched left parentheses in the right position. 
      Establish prefix and array a to indicate the number of unmatched left parentheses in the current position. 
      When encountering left bracket prefix and + 1, right bracket prefix and - 1, then the rule is deduced by examples. 
      ( ( ( ) ) ) 
      1 2 3 2 1 0 
      When A and B are exchanged, the sum of prefixes from a to (b-1) is reduced by 2 (less) than the sum of prefixes before the change.
      One'+1', one more'-1', so it's 2 less than before. The prefix and appearing-1 do not match the parentheses.
      therefore 
      When the exchange between the left'('and the right can satisfy the equilibrium string still in parentheses, it must be in the interval [a,b-1]. 
      Minimum >= 2 
      So the problem is transformed into finding whether the prefix and the minimum value of the array in the interval [a,b-1] satisfy >= 2. 
      The RMQ algorithm based on ST or the line segment tree can be used to find the minimum value of the interval. 
/*
  RMQ
  AC:204ms
*/
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#define MM(s,q) memset(s,q,sizeof(s))
#define INF 0x3f3f3f3f
#define MAXN 100005
#define Lchild id<<1
#define Rchild (id<<1)+1
using namespace std;
char s[MAXN];
int num[MAXN], dp[MAXN][30];
void init( int n ) {
    for ( int i = 1; i <= n; i++ )
        dp[i][0] = num[i];
    for ( int j = 1; ( 1 << j ) <= n; j++ )
        for ( int i = 1; i + ( 1 << j ) - 1 <= n; i++ )
            dp[i][j] = min( dp[i][j - 1], dp[i + ( 1 << ( j - 1 ) )][j - 1] );
}
int RMQ( int i, int j ) {
    int k = ( int )( log( j - i + 1 ) / log( 2 ) );
    return min( dp[i][k], dp[j - ( 1 << k ) + 1][k] );
}
int main() {
    int n, q;
    while ( cin >> n >> q ) {
        scanf( "%s", s );

        int sum = 0;
        for ( int i = 0; i < n; i++ ) {
            if ( s[i] == '(' ) sum++;
            else sum--;
            num[i + 1] = sum;
        }
        init( n );

        int a, b;
        while ( q-- ) {
            scanf( "%d%d", &a, &b );
            int sign = 0;
            a--, b--;
            if ( a > b ) swap( a, b );
            if ( s[a] == s[b] ) sign = 1; // (or)
            else  if ( s[a] == ')' ) sign = 1; //  )) Or)(
            else if ( RMQ(a+1,b)>=2 ) sign=1;

                printf( "%s\n", sign == 1 ? "Yes" : "No" );
        }
    }
}
/*
  Direct violence
  AC:3184ms
*/
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#define MM(s,q) memset(s,q,sizeof(s))
#define INF 0x3f3f3f3f
#define MAXN 100005
#define Lchild id<<1
#define Rchild (id<<1)+1
using namespace std;
char s[MAXN];
int main() {
    int n, q;
    while ( cin >> n >> q ) {
        scanf( "%s", s );
        int a, b;
        while ( q-- ) {
            scanf( "%d%d", &a, &b );
            int sign = 0;
            a--, b--;
            if(a>b) swap(a,b);
            if ( s[a] == s[b] ) sign = 1; // (or)
            else  if ( s[a] == ')' ) sign = 1; //  )) Or)(
            else {   // Only ()
                swap( s[a], s[b] );
                int sum = 0;
                for ( int i = 0; i < n; i++ ) {
                    if ( s[i] == '(' ) sum++;
                    else sum--;
                    if ( sum < 0 ) break;
                    if ( i == n - 1 ) sign = 1;
                }
                swap( s[a], s[b] );
            }
            printf( "%s\n", sign == 1 ? "Yes" : "No" );
        }
    }
}

Posted by zhTonic on Mon, 08 Jul 2019 17:23:08 -0700