G(1809): Parenthesis题目
Submit Page Summary Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 25 Solved: 7
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
这个代码主要是为了熟悉一下树状数组的运用。
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 100005
int s[MAXN];
char st[100005];
int n;
int lowbit(int x){return x&(-x);}
int sum(int x){
int sum=0;
while(x){
sum+=s[x];
x-=lowbit(x);
}
return sum;
}
void add(int x,int a){
while(x<=n){
s[x]+=a;
x+=lowbit(x);
}
}
int main()
{
int q;
while(~scanf("%d%d",&n,&q))
{
memset(s,0,sizeof(s));
scanf("%s",st);
for(int i=1;i<=n;i++)
{
if(st[i-1]=='(')
add(i,1);
else
add(i,-1);
}
int a,b;
while(q--)
{
scanf("%d%d",&a,&b);
bool flag=true;
if(a>b)
{
a=a+b;
b=a-b;
a=a-b;
}
if(st[a-1]=='('&&st[b-1]==')')
{
while(a<b)
{
if(sum(a)-2<0)
{
flag=false;
break;
}
a++;
}
}
if(flag==false)
printf("No\n");
else
printf("Yes\n");
}
}
return 0;
}
普通求和,比上面的代码优化了好多倍
#include<iostream>
using namespace std;
#define MAXN 100005
int sum[MAXN];
char s[MAXN];
int main()
{
int n,q;
int a,b;
while(~scanf("%d%d",&n,&q))
{
getchar();
for(int i=1;i<=n;i++)
{
scanf("%c",&s[i]);
if(s[i]=='(')
sum[i]=sum[i-1]+1;
else
sum[i]=sum[i-1]-1;
}
while(q--)
{
scanf("%d%d",&a,&b);
if(a>b)
swap(a,b);
bool flag=true;
if(s[a]=='('&&s[b]==')')
for(int i=a;i<b;i++)
{
if(sum[i]<2)
{
flag=false;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
线段树优化,区间最小,比上面代码好
#include<cstdio>
#include<algorithm>
#define INF 100005
#define MAXN 100005
using namespace std;
struct
{
int l,r;
int min;
}tree[MAXN<<2];
int sum[MAXN];
char st[MAXN];
void BuildTree(int i,int L,int R)
{
tree[i].l=L;
tree[i].r=R;
if(L==R)
{
tree[i].min=sum[L];
return ;
}
BuildTree(i<<1,L,(L+R)>>1);
BuildTree(i<<1|1,((L+R)>>1)+1,R);
tree[i].min=min(tree[i<<1].min,tree[i<<1|1].min);
return ;
}
int QueryTree(int L,int R,int i)
{
if(L<=tree[i].l&&R>=tree[i].r)
{
return tree[i].min;
}
int mi=INF;
if(L<=tree[i<<1].r)
mi=QueryTree(L,R,i<<1);
if(R>=tree[i<<1|1].l)
mi=min(mi,QueryTree(L,R,i<<1|1));
return mi;
}
int main()
{
int n,q,l,r;
while(~scanf("%d%d",&n,&q))
{
sum[0]=0;
scanf("%s",st);
for(int i=1;i<=n;i++)
{
if(st[i-1]=='(')
sum[i]=sum[i-1]+1;
else
sum[i]=sum[i-1]-1;
}
BuildTree(1,1,n);
while(q--)
{
scanf("%d%d",&l,&r);
if(l>r)
swap(l,r);
if(st[l-1]=='('&&st[r-1]==')'&&QueryTree(l,r-1,1)<2)
printf("No\n");
else
printf("Yes\n");
}
}
return 0;
}