2016湖南省赛G题。

终于还是写完了。。懒癌复发。。。原来可以用线段树。判断区间内最小的前缀是否小于2就行了。。。之前比赛的时候没有想到用这个方法。。。虽然自己会一点线段树。。但是可惜没写出来。。总的来说还是太菜了吧。要多刷刷线段树。。刷完线段树接下来就是最短路、最小生成树、DP了。
G - Parenthesis
Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

Bobo has a balanced parenthesis sequence P=p  1 p  2…p  n of length n and q questions.
The i-th question is whether P remains balanced after p  ai and p  bi  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≤10  5,1≤q≤10  5).
The second line contains n characters p  1 p  2…p  n.
The i-th of the last q lines contains 2 integers a  i,b  i (1≤a  i,b  i≤n,a  i≠b  i).

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

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const int INF=0x3f3f3f3f;
int sum[MAXN<<2];
int pre[MAXN];
char s[MAXN];

void push_up(int k)
{
    sum[k]=min(sum[k<<1],sum[k<<1|1]);
}
void build(int l,int r,int k)
{
    if(l==r)
    {
        sum[k]=pre[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    push_up(k);
}

int query(int L,int R,int l,int r,int k)
{
    if(L<=l&&R>=r) return sum[k];
    int ans=INF;
    int mid=(l+r)>>1;
    if(L<=mid) ans=min(ans,query(L,R,l,mid,k<<1));
    if(R>mid) ans=min(ans,query(L,R,mid+1,r,k<<1|1));
    return ans;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        scanf("%s",s+1);
        for(int i=1;i<=n;i++)
        {
            if(s[i]=='(') pre[i]=pre[i-1]+1;
            else pre[i]=pre[i-1]-1;
        }
        build(1,n,1);
        while(m--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            if(l>r)swap(l,r);
            if(s[l]==s[r]||(s[l]==')'&&s[r]=='(')) printf("Yes\n");
            else
            {
                if(query(l,r-1,1,n,1)<2) printf("No\n");
                else printf("Yes\n");
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值