1809: Parenthesis
Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 1500 Solved: 398
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').
题目大意:
给你一个长度为N的括号匹配串,然后有q个查询,表示交换两个位子上的括号之后,询问你字符串还是否构成括号匹配。
思路:
首先预处理出一个前缀和sum【i】,设定(表示1,)表示-1.那么我们开始分类讨论:
①a【x】==a【y】,那么结果一定是Yes.
②a【x】==‘)’&&a【y】==‘(’,那么结果也一定是Yes.因为如果左边的右括号放置在了右边,可以和放置在左边的这个左括号进行匹配,原串保证是匹配的,所以这样交换的结果也一定是Yes.
③a【x】==‘(’&&a【y】==‘)’,那么考虑对前缀和的影响:
撤销x位子上的左括号:从x-------------->n 前缀和全部减去1
撤销y位子上的右括号:从y-------------->n 前缀和全部加上1
放置x位子上那个右括号:从x----------->n 前缀和全部减去1
放置y位子上那个左括号:从y----------->n 前缀和全部加上1
显然,如果有某个前缀和的位子上出现了负数,那么此时这个字符串一定是构不成括号匹配的,所以我们只要判定影响到的部分是否会出现负数即可。
显然,从y---------->n的部分都加上了2,从x---------->y-1的部分都减去了1.
那么我们只要查询之前前缀和中区间【x,y-1】中的最小值是否大于等于2即可,如果是,结果就是Yes.否则就是No.
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define maxn 100050 #define inf_int 2e9 int sum[maxn*3],val[maxn]; char s[maxn]; void push_up(int i){ sum[i] = min(sum[i<<1],sum[i<<1|1]); } void build(int i,int l,int r){ if(l==r){ sum[i] = val[l]; return; } int mid = (l+r) >> 1; build(i<<1,l,mid); build(i<<1|1,mid+1,r);//i<<1|1 把i左移1位,然后和1按位或 push_up(i); } int querry(int i,int l,int r,int L,int R){ if(L<=l && R>=r) return sum[i]; int ans = inf_int; int mid = (l+r) >> 1; if(L<=mid) ans = min(ans,querry(i<<1,l,mid,L,R)); if(R>mid) ans = min(ans,querry(i<<1|1,mid+1,r,L,R)); return ans; } int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { scanf("%s",s+1); memset(val,0,sizeof(val)); for(int i=1;i<=n;i++){ if(s[i]=='(') val[i] = val[i-1] + 1; else val[i] = val[i-1] - 1; } build(1,1,n); while(m--){ int l,r; scanf("%d%d",&l,&r); if(l>r) swap(l,r); if(s[l]=='(' && s[r]==')'){ if(querry(1,1,n,l,r-1)<2) printf("No "); else printf("Yes "); } else printf("Yes "); } } return 0; }