CSU 1809 - Parenthesis - [prefix sum + maintenance interval minimum] [segment tree/RMQ]

Topic link: http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1809

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

 

Title:

Now give a string of parentheses of length n, guaranteed to be a balanced string of parentheses;

Then give q queries, each query has two values ​​a, b, representing the query to exchange P[a] and P[b], will the bracket string become unbalanced.

 

answer:

First, we define a preSum array, which represents the prefix sum of the bracket sequence. When a '(' is encountered, 1 is added, and when a ')' is encountered, 1 is subtracted;

In this way, the bracket sequence is a balanced sequence $\Leftrightarrow$ preSum[n]==0, and preSum[i]≥0 for $\forall$i=1~n;

Then we have the following three cases:

  1. P[a]==P[b], this situation is obviously no different from the original exchange, and it is obviously balanced;
  2. P[a]=')' and P[b]='(', in this case, preSum[1]~preSum[a-1] will not change, preSum[a]~preSum[b-1 ] will be $+=2$, and preSum[b]~preSum[n] will not change. In this way, the new bracket sequence generated after the exchange still satisfies preSum[n]==0, and for $ \forall$i=1~n all have preSum[i]≥0, then obviously the bracket sequence is still a balanced sequence;
  3. P[a]='('and P[b]=')', in this case, preSum[1]~preSum[a-1] will not change, preSum[a]~preSum[b-1 ] will be $-=2$, and preSum[b]~preSum[n] will not change, so obviously the key lies in preSum[a]~preSum[b-1], we know that once there is a preSum[i ]<0, this bracket sequence is unbalanced, so we must ensure that preSum[a]~preSum[b-1] are all greater than or equal to 2.

Therefore, we can use the segment tree or RMQ to maintain the minimum value of the preSum[] array. For each query, we only need to find out whether the minimum value of preSum[i] in the interval [a, b] is greater than 2.

 

AC code:

①Line segment tree:

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;

const int maxn=1e5+10;
const int INF=0x3f3f3f3f;

int n,q;
char str[maxn];
int preSum[maxn];

struct Node{
    int l,r;
    int val;
}node[4*maxn];
void pushup(int root)
{
    node[root].val =min(node[root* 2 ].val,node[root* 2 + 1 ].val);
}
void build(int root,int l,int r)
{
    node[root].l=l; node[root].r=r;
    if(l==r) node[root].val=preSum[l];
    else
    {
        int mid=l+(r-l)/2;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
        pushup(root);
    }
}
int query(int root,int st,int ed)
{
    if(ed<node[root].l || node[root].r<st) return INF;
    if(st<=node[root].l && node[root].r<=ed) return node[root].val;
    else return min(query(root*2,st,ed),query(root*2+1,st,ed));
}

intmain ()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        scanf("%s",str+1);

        preSum[0]=0;
        for(int i=1;i<=n;i++) preSum[i]=preSum[i-1]+(str[i]=='('?1:-1);

        build(1,1,n);
        for(int i=1,a,b;i<=q;i++)
        {
            scanf("%d%d",&a,&b);
            if(a>b) swap(a,b);

            if( str[a]==str[b] || (str[a]==')' && str[b]=='(') ) printf("Yes\n");
            else if(query(1,a,b-1)>=2) printf("Yes\n");
            else printf("No\n");
        }
    }
}

②RMQ:

#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;

const int maxn=1e5+10;
const int INF=0x3f3f3f3f;

int n,q;
char str[maxn];
int preSum[maxn];

struct _RMQ{
    int Mnum[maxn][20]; //int(log(maxn)/log(2.0))
    void init(int num[])
    {
        for(int i=1;i<=n;i++) Mnum[i][0]=num[i];
        int j_max=(log(n)/log(2));
        for(int j=1;j<=j_max;j++)
        {
            for(int i=1;i<=n;i++)
            {
                if(i+(1<<j)-1 <= n)
                    Mnum[i][j]=min(Mnum[i][j-1],Mnum[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int query(int l,int r)
    {
        int k=log(r-l+1)/log(2);
        return min(Mnum[l][k],Mnum[r-(1<<k)+1][k]);
    }
}RMQ;

intmain ()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        scanf("%s",str+1);

        preSum[0]=0;
        for(int i=1;i<=n;i++) preSum[i]=preSum[i-1]+(str[i]=='('?1:-1);

        RMQ.init(preSum);
        for(int i=1,a,b;i<=q;i++)
        {
            scanf("%d%d",&a,&b);
            if(a>b) swap(a,b);

            if( str[a]==str[b] || (str[a]==')' && str[b]=='(') ) printf("Yes\n");
            else if(RMQ.query(a,b-1)>=2) printf("Yes\n");
            else printf("No\n");
        }
    }
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325338103&siteId=291194637
Recommended