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
分析:对于括号序列匹配,是有一些实用的结论的,如果一个序列是合法的,那么以左括号为+1,右括号为-1,前缀和任何时候都不会是负数。
所以对于原序列来说,显然满足上述条件。
对于每个询问,如果两个符号相同显然是Yes
同样,如果左边的符合是-1,那么也一定是Yes,因为移动之后使得中间这段前缀和变大。
那剩下的就是统计区间最小值的问题了,用个RMQ就ok了。(或者线段树)
当然,由于交换的影响只是会让[L,R-1]这段区间的前缀和-2,
所以只要统计这段区间里的前缀和有小于2的即可。
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100010
int Minnum[maxn][20];
int N,Q;
char s[maxn];
void RMQ()
{
for(int j=1; (1<<j)<=N; ++j)
for(int i=1; i<=N; ++i)
{
if(i+(1<<j)-1<=N)
{
Minnum[i][j]=min(Minnum[i][j-1],Minnum[i+(1<<j>>1)][j-1]);
}
}
}
int main()
{
while(~scanf("%d%d",&N,&Q))
{
scanf("%s",s+1);
int num=0;
for(int i=1; i<=N; ++i)
{
num+=(s[i]=='('?1:-1);
Minnum[i][0]=num;
}
RMQ();
int le,ri,k,Min;
while(Q--)
{
scanf("%d%d",&le,&ri);
if(ri<le)
swap(le,ri);
if((s[le]==')'&&s[ri]=='(')||s[le]==s[ri])
{
printf("Yes\n");
continue;
}
ri-=1;
k=(int)(log(ri-le+1.0)/log(2.0));
Min=min(Minnum[le][k],Minnum[ri-(1<<k)+1][k]);
if(Min<2)
printf("No\n");
else
printf("Yes\n");
}
}
return 0;
}
RMQ详解:http://blog.csdn.net/blesslzh0108/article/details/70828674
参考博客:
浅蓝