CSU 1809 Parenthesis(RMQ||线段树)

115 篇文章 0 订阅
3 篇文章 0 订阅

Parenthesis

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

分析:对于括号序列匹配,是有一些实用的结论的,如果一个序列是合法的,那么以左括号为+1,右括号为-1,前缀和任何时候都不会是负数。
所以对于原序列来说,显然满足上述条件。

对于每个询问,如果两个符号相同显然是Yes
同样,如果左边的符合是-1,那么也一定是Yes,因为移动之后使得中间这段前缀和变大。
那剩下的就是统计区间最小值的问题了,用个RMQ就ok了。(或者线段树)
当然,由于交换的影响只是会让[L,R-1]这段区间的前缀和-2,
所以只要统计这段区间里的前缀和有小于2的即可。

代码:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define maxn 100010

int Minnum[maxn][20];
int N,Q;
char s[maxn];

void RMQ()
{
    for(int j=1; (1<<j)<=N; ++j)
        for(int i=1; i<=N; ++i)
        {
            if(i+(1<<j)-1<=N)
            {
                Minnum[i][j]=min(Minnum[i][j-1],Minnum[i+(1<<j>>1)][j-1]);
            }
        }
}

int main()
{
    while(~scanf("%d%d",&N,&Q))
    {
        scanf("%s",s+1);
        int num=0;
        for(int i=1; i<=N; ++i)
        {
            num+=(s[i]=='('?1:-1);
            Minnum[i][0]=num;
        }
        RMQ();
        int le,ri,k,Min;
        while(Q--)
        {
            scanf("%d%d",&le,&ri);
            if(ri<le)
                swap(le,ri);
            if((s[le]==')'&&s[ri]=='(')||s[le]==s[ri])
            {
                printf("Yes\n");
                continue;
            }
            ri-=1;
            k=(int)(log(ri-le+1.0)/log(2.0));
            Min=min(Minnum[le][k],Minnum[ri-(1<<k)+1][k]);
            if(Min<2)
                printf("No\n");
            else
                printf("Yes\n");
        }
    }
    return  0;
}



RMQ详解:http://blog.csdn.net/blesslzh0108/article/details/70828674
参考博客:
浅蓝

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值