问题 E: Mouse and Parenthesis
时间限制: 1 Sec 内存限制: 128 MB提交: 46 解决: 10
[ 提交 ][ 状态 ][ 讨论版 ]
题目描述
Tom has m same balanced parenthesis sequence P=p1 p2…pn of length n.
This day Jerry comes into Tom's room and swaps one pair of parenthesis in every sequence.
Tom and Jerry both like balanced parenthesis sequence, so Jerry wants to know whether each P remains balanced after pai and pbi swapped.
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').
输入
The first line contains an integers T (T≤20), which indicates the number of test cases.
For each case:
The first line contains two integers n,m.The second line contains n characters p1 p2…pn.
The i-th of the last m lines contains 2 integers ai,bi (1≤ai,bi≤n,ai≠bi).
⋅ for 50% data, 1≤n≤50,1≤q≤1000.
⋅ for 100% data, 1≤n≤100000,1≤q≤100000.
输出
样例输入
2
4 2
(())
1 3
2 3
2 1
()
1 2
样例输出
Case #1:
No
Yes
Case #2:
No
通过思考我们将交换的情况分开讨论,就会发现如果交换的是相同的yes,)(交换一定也是yes,那么就差()变成)(情况,这就涉及到一个括号怎样才是合法的,因为题目中给出了,原本序列是合法的这个条件,所以保证了,()的数量相等;
我们发现)合法的条件是他之前存在大于等于1的未匹配的(,而(永远是合法的,交换以后一定要注意可能不合法的部分出现在[a,b-1],而如果这里的)前面的(小于2(为啥是小于2呢,因为用(换),这部分的)前面的(都少了一个,还多了一个)匹配掉一个(,所以少了两个()但是我们如果我们每次遍历[a,b-1]这个区间会超时,所以我们用线段树来维护区间的最小值
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=100000+10;
string a;
int num[maxn],n,m;
struct node
{
int s;
int e;
int value;
}nodes[4*maxn];
int min(int a,int b)
{
if(a<b) return a;
else return b;
}
int init(int s,int e,int index)
{
nodes[index].s=s;
nodes[index].e=e;
if(s==e)
{
nodes[index].value=num[s];
return num[s];
}
int m=(s+e)/2;
nodes[index].value=min(init(s,m,2*index),init(m+1,e,2*index+1));
return nodes[index].value;
}
int query(int s,int e,int index)
{
int m=(nodes[index].s+nodes[index].e)/2;
if(s==nodes[index].s&&e==nodes[index].e) return nodes[index].value;
else if(nodes[index].s<=s&&e<=m) return query(s,e,2*index);
else if(s>=m+1&&e<=nodes[index].e) return query(s,e,2*index+1);
else return min(query(s,m,2*index),query(m+1,e,2*index+1));
}
int main()
{
//freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
memset(num,0,sizeof(num));
scanf("%d%d",&n,&m);
printf("Case #%d:\n",t);
cin>>a;
int temp=0;
for(int i=0;i<a.size();i++)
{
if(a[i]=='(') temp++;
else temp--;
num[i]=temp;
}
//buildtree(0,n-1,1);
init(0,n-1,1);
for(int i=1;i<=m;i++)
{
int p1,p2;
scanf("%d%d",&p1,&p2);
if(p1>p2)
{
temp=p1;
p1=p2;
p2=temp;
}
p1--;
p2--;
if(a[p1]==a[p2]) printf("Yes\n");
else if(a[p1]=='('&&a[p2]==')')
{
if(query(p1,p2-1,1)<2) printf("No\n");
else printf("Yes\n");
}
else printf("Yes\n");
}
}
return 0;
}