首页 > 代码库 > csu 1809 Parenthesis(线段树)

csu 1809 Parenthesis(线段树)

#include<bits/stdc++.h>using namespace std;const int maxn=1e5+5;char s[maxn];int  pre[maxn],Min[maxn<<2];int n,q,u,v;/*	给一个长度为n(<=1e5)的只有()的匹配字符串,q(<=1e5)次询问	每次询问在原串上交换两个字符,问交换之后是否还是合法子串	如果把(值为1,)值为-1,那么一个区间前缀和不存在<0,并且	最终的和为0,肯定就是一个匹配字符串	那么交换的两个字符是相同的,肯定是合法的	如果交换的是 )(,那么肯定也是合法的	如果交换的是(),那么就要考虑[l,r)之间在交换后是否会产生	负数,交换的结果是,[l,r)都会-2,那么求[l,r)之间的最小值	写个线段树就好了*/void build(int rt,int l,int r){	if(l==r){		Min[rt]=pre[l];		return ;	}	int mid=(l+r)>>1;	build(rt<<1,l,mid);	build(rt<<1|1,mid+1,r);	Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);}int query(int rt,int l,int r,int ql,int qr){	if(ql<=l&&qr>=r)return Min[rt];		int mid=(l+r)>>1;	int res=INT_MAX;	if(ql<=mid)res=min(res,query(rt<<1,l,mid,ql,qr));	if(qr>mid)res=min(res,query(rt<<1|1,mid+1,r,ql,qr));	return res;}int main(){	int n,q,u,v;	while(~scanf("%d%d",&n,&q)){		getchar();gets(s);		for(int i=1;i<=n;i++){			if(s[i-1]==‘(‘)pre[i]=1;			else pre[i]=-1;			pre[i]+=pre[i-1];		}		build(1,1,n);				while(q--){			scanf("%d%d",&u,&v);			if(u>v)swap(u,v);			if(s[u-1]==s[v-1])puts("Yes");			else if(s[v-1]==‘(‘)puts("Yes");			else{				int a=query(1,1,n,u,v-1);				if(a>1)puts("Yes");				else puts("No");			}		}	}	return 0;}

  

csu 1809 Parenthesis(线段树)