题目描述
解题思路
40分思想:
因为右括号能够盖住左括号,所以当右括号的个数超过左括号时,其就会需要多一个括号进行匹配,再加上每个括号会与距离其最近的括号匹配
,所以这是一个先进后出
的结构,所以我们可以用栈解决,时间复杂度
100分思路:
上一种思路之所以慢是因为它每次都要一遍循环找括号,然后由于令人讨厌的单点修改,于是构成了区间查询和单点修改与信息维护
,这时我们可以用到一个骚气的东西线段树!
用线段树维护括号数就可以达到快速求解的目的了,时间复杂度
注意,若您线段树的代码超时了,您可以在
https://blog.csdn.net/xuxiayang/article/details/81021585获得一些经验
40分代码
#include<stack>
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,x,y,l,r,ansl,ansr;
char c[150001],q[101];
stack<char>s;
int main()
{
freopen("elf.in","r",stdin);
freopen("elf.out","w",stdout);
cin>>n>>m>>c+1;
while(m--)
{
cin>>q;
if(q[0]=='Q')
{
cin>>x>>y;
while(s.size()) s.pop();
if(x==y) {if(c[x]=='(') printf("0 1\n");else printf("1 0\n");continue;}
ansl=0;ansr=0;
for(int i=x;i<=y;i++)
if(c[i]=='(') s.push(c[i]);//左括号入栈
else
{
if(s.size()) s.pop();//出栈=抵消
else ansl++;//没有抵消说明多出了一个右括号,那么我们需要新增一个左括号维护
}
ansr=s.size();//若栈中还有元素,说明还有左括号未被匹配,则需要加上该数量的右括号
printf("%d %d\n",ansl,ansr);
}
else
{
cin>>x;
if(c[x]=='(') c[x]=')';
else c[x]='(';
}
}
}
AC代码
#include<iostream>
#include<cstdio>
#define lson k<<1
#define rson k<<1|1
using namespace std;int n,m,x,y,ansl,ansr,f;
char c[150001],q[51],ask;
struct node{int l,r,lm,rm;}t[600001];
void write(int x)//输出流
{
if(x>9) write(x/10);putchar(x%10+48);
return;
}
void judge(node &k,node &x,node &y)//合并,传递信息
{
k.lm=y.lm+max(0,x.lm-y.rm);
k.rm=x.rm+max(0,y.rm-x.lm);
return;
}
void build(int k,int l,int r)//建树
{
t[k].l=l;t[k].r=r;
if(l==r)
{
t[k].lm=c[l]=='('?1:0;
t[k].rm=c[l]==')'?1:0;//初始化
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
judge(t[k],t[lson],t[rson]);//传递信息
return;
}
void add(int k,int x)
{
if(t[k].l==x&&t[k].r==x)
{
t[k].lm^=1;
t[k].rm^=1;//取反=单点修改
return;
}
if(t[k].l==t[k].r) return;//到达叶子节点结束
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid) add(lson,x);else add(rson,x);
judge(t[k],t[lson],t[rson]);//传递信息
return;
}
node query(int k,int x,int y)
{
if(t[k].l==x&&t[k].r==y) return t[k];//到达目标区间传递信息返回
if(t[k].l==t[k].r) return (node){t[k].l,t[k].r,0,0};//到达叶子节点返回空
int mid=(t[k].l+t[k].r)>>1;
if(y<=mid) return query(lson,x,y);
if(x>mid) return query(rson,x,y);
node ls,rs,ans;
ls=query(lson,x,mid);//访问左区间
rs=query(rson,mid+1,y);//访问右区间
judge(ans,ls,rs);//合并,传递信息
return ans;
}
int main()
{
freopen("elf.in","r",stdin);
freopen("elf.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%s",c+1);
build(1,1,n);
while(m--)
{
scanf("%s %d",q,&x);
if(q[0]=='Q')
{
scanf("%d",&y);
node ans=query(1,x,y);//查询
write(ans.rm);putchar(32);write(ans.lm);putchar(10);//输出
}
else add(1,x);//修改
}
}