2016湖南省赛 G Parenthesis [RMQ]

这个题,给你一串括号序列 问你交换 ai,bi两个位置的括号,原串是否依然匹配

题目分析,对于一个括号序列,我们只要找到一个右括号,在它之前没有左括号与它匹配,那么就是不匹配的序列,将左括号记为-1 右括号记为1 求前缀和 如果前缀和 >=1 那么一定就不匹配了
由于有很多查询,所以,我们用Rmq 求 [ai,bi) 区间最大值, 只有在ai 和bi 是 从 “(” 和”)” 换成“)”“(”时,采用可能会从匹配变成不匹配,那么交换后 [ai,bi)区间内的数都会+2 ,我们只要求区间最大 +2是否>=1 即可

//这个题wa了很多次,因为我理所应当把 ai

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn=1e5+50;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
typedef long long LL;
int st[maxn];
int d[maxn][18];
int n,q;
void predig()
{
    memset(d,-inf,sizeof(d));
    for (int i = 1; i<=n; i++)
    {
        d[i][0] = st[i];
    }

    for (int j = 1; (1 << j) <= n; j++)
    {
        for (int i = 1; (i + (1 << j) - 1)<=n; i++)
        {
            d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
        }
    }
}

int rmq(int l, int r)
{
    int k = 0;
    while (1 << (k + 1) <= (r - l + 1)) k++;
    return max(d[l][k], d[r - (1 << k) + 1][k]);
}
int main()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        cl(st);
        string s;
        cin>>s;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]=='(')st[i+1]=st[i]-1;
            else st[i+1]=st[i]+1;
        }
        predig();
        for(int i=1;i<=q;i++)
        {
            int ai,bi;
            scanf("%d%d",&ai,&bi);
             if (ai > bi) swap (ai,bi);
            int t=rmq(ai,bi-1);
            //cout<<t<<endl;XA
            if(s[bi-1]==')'&&s[ai-1]=='(')t+=2;

            if(t>=1) puts("No");
            else puts("Yes");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/becky_w/article/details/80160111
RMQ