括号匹配 RMQ/暴力

来源:互联网 发布:淘宝店铺介绍填写 编辑:程序博客网 时间:2024/05/18 09:57

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

題意: 给出一个已经匹配的括号序列,任意的交换两个位置的括号,判断是否匹配,如果匹配输出 Yes 不匹配输出 No。

判断括号是否匹配的方法

   int sum=0;   for ( int i = 0; i < n; i++ ) {                    if ( s[i] == '(' ) sum++;  // 遇到‘(’ sum+1                    else sum--;    // 遇到‘)’ sum-1                    if ( sum < 0 ) break;  // 如果 sum<0 则括号不匹配   }

分析参考:http://blog.csdn.net/bcwan_/article/details/52436229

分析:1.当左边的字符与右边的字符一样时,交换一定为括号平衡串       2.当左边的字符为')'时,交换一定为括号平衡串.因为一开始是平衡串,       如果左边的字符')'与右边的'('交换,那么此时交换的两个必能匹配为一对,       如果左边的字符')'与右边的')'交换,那么此时交换的两个字符相同,满足1.       3.当左边的字符为'('时,满不满足和右边位置左括号未匹配的个数有关.       建立前缀和数组a,表示当前位置左括号未匹配的个数,       当遇到左括号时前缀和+1,右括号时前缀和-1,那么由个例推出规律       ( ( ( ) ) )       1 2 3 2 1 0       当a和b交换时,相对于改变前的前缀和,从a至(b-1) 前缀和都要减2(少了      一个‘+1’,多了一个‘-1’,所以比原来减少2),前缀和出现-1,括号就不匹配,      所以       当左边的'('与右边的交换能满足仍为括号平衡串的必须是在区间[a,b-1]内       的最小值>=2       所以问题转化为求区间[a,b-1]内的前缀和数组最小值是否满足>=2       可以用基于ST的RMQ算法,也可以用线段树求区间最小值 
/*  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)+1using 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; // ( ( 或 ) )            else  if ( s[a] == ')' ) sign = 1; //  ) ) 或 ) (            else if ( RMQ(a+1,b)>=2 ) sign=1;                printf( "%s\n", sign == 1 ? "Yes" : "No" );        }    }}
/*  直接暴力  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)+1using 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; // ( ( 或 ) )            else  if ( s[a] == ')' ) sign = 1; //  ) ) 或 ) (            else {   // 只剩下 ( )                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" );        }    }}
0 0