CSU 1809 Parenthesis 思维+线段树

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').

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

Hint

Source

湖南省第十二届大学生计算机程序设计竞赛

 

 

题目大意:

给你一个长度为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\n");
                else printf("Yes\n");
            }
            else printf("Yes\n");
        }
    }
    return 0;
}

 

posted on 2017-08-01 10:39  九月旧约  阅读(198)  评论(0编辑  收藏  举报

导航