解题思路:线段树+前缀和。计算出前缀和,’(‘就加一,’(‘就减一。考虑三种情况,如果是s[x]==s[y]或者s[x]= =’)’&&s[y]= = ‘(’,那么就直接是yes。对于s[x]= = ‘(’&&s[y]= =’)’,判断在[x,y)的最小的前缀和-2如果<0,就是no,要不然就是yes.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int random(int n){
return (int)((ll)rand()*rand())%n;
}
char s[N];
int tree[N<<4];
void update(int rt,int left,int right,int k,int c){
if(left == right){
tree[rt] = c;
return;
}
int mid = (left+right)/2;
if(k <= mid) update(2*rt,left,mid,k,c);
else update(2*rt+1,mid+1,right,k,c);
tree[rt] = min(tree[2*rt],tree[2*rt+1]);
}
int query(int rt,int left,int right,int l,int r){
if(left >= l && right <= r){
return tree[rt];
}
int ret = N,mid = (left+right)/2;
if(l <= mid) ret = min(ret,query(2*rt,left,mid,l,r));
if(r > mid) ret = min(ret,query(2*rt+1,mid+1,right,l,r));
return ret;
}
int main(){
//freopen("out.txt","w",stdout);
int n,q;
scanf("%d%d",&n,&q);
scanf("%s",s+1);
int sum = 0;
for(int i = 1;i <= n;i++){
if(s[i] == '(') sum += 1;
else sum -= 1;
update(1,1,n,i,sum);
}
while(q--){
int x,y;
scanf("%d%d",&x,&y);
if(x>y)swap(x,y);
if(s[x]==s[y]||(s[x]==')'&&s[y]=='(')){
printf("Yes\n");continue;
}
x = query(1,1,n,x,y-1);
if(x-2 < 0) printf("No\n");
else printf("Yes\n");
}
return 0;
}