[BZOJ 4350] Bracket sequence to fight pig man again (interval DP)

[BZOJ 4350] Bracket sequence fights pig man again

Description

The bracket sequence and Pig Man fought again.
As we all know, a bracket sequence is a sequence consisting of only (and), we call a bracket
sequence S valid if and only if:
1.( ) is a valid bracket sequence.
2. If A is a valid bracket sequence, then (A) is a valid bracket sequence.
3. If A and B are valid bracket sequences, then AB is a valid bracket sequence.
Let's consider match[i] to indicate that the i-th opening bracket from left to right corresponds to the right
bracket, and now he gets a bracket sequence of length 2n, giving you m information, the i
-th information The shape is like ai,bi, which means match[ai]<match[bi], and you want to restore this sequence.
But you find that the information that this pig man is telling you, there may be multiple bracket sequences legal; it
may even tell you a message that there is no legal bracket sequence!
You have recently learned the modulo operation, and you want to know the result of taking the answer modulo 998244353 (7 17 2^23+1)
, which is a prime number.


The first line of Input is a positive integer T, T<= 5, indicating the number of data groups.
For each set of data, the first line contains an n, m, where n means there are several left parentheses, and m means the number of information.
Next m lines, each line with two numbers ai, bi, 1 <= ai, bi <= n.

Output
For each set of data, output a number representing the answer.

Solution

1. For the constraint match[i]

Supplement: Find two-dimensional interval sum method: O(n^2) preprocessing prefix sum, O(1) query result:

For v[x1...x2][y1...y2] (x1<=x2,y1<=y2),

ans=v[x2][y2]-v[x1-1][y2]-v[x2][y1-1]+v[x1-1][y1-1],即:

inline ll sum(ll x1,ll x2,ll y1,ll y2){
    return v[x2][y2]-v[x1-1][y2]-v[x2][y1-1]+v[x1-1][y1-1];
}

2. For the to-be-processed interval [l, r], divide it with the position of the right parenthesis corresponding to the first left parenthesis and transfer it:

(1) the closing parenthesis corresponding to the first parenthesis is next to it, if and only if there is no restriction on it after it,

That is, sum(l+1,r,l,l)=0, the transfer is f[l][r]=(f[l][r]+f[l+1][r])%mod;

(2) The right parenthesis corresponding to the first parenthesis is on the right side of the entire interval, if and only if there is no restriction on the back,

That is, sum(l,l,l+1,r)=0, the transfer is the same as above;

(3) When the right parenthesis corresponding to the first parenthesis is in the interval and is on the right side of the kth left parenthesis, it should satisfy:

a. The right half has no restrictions on the left half, that is, sum(k+1,r,l,k)=0;

b. When the first bracket does not limit the left half of the interval, that is, sum(l,l,l+1,k)=0;

The transfer is the number of solutions plus the number of solutions on the left , that is, f[l][r]=(f[l][r]+f[l+1][k] f[k+1][r ])%mod;

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;

ll t,n,m,v[500][500],f[500][500]; 
const ll mod=998244353;

inline ll rd(){
    ll x=0;
    bool f=0;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-')f=1;
        c=getchar();
    }
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?-x:x;
}

void init(){
    n=rd();
    m=rd();
    memset(f,0,sizeof(f));
    memset(v,0,sizeof(v));
    for(ll i=1;i<=m;++i)v[rd()][rd()]=1;
    for(ll i=1;i<=n;++i)
        for(ll j=1;j<=n;++j)
            v[i][j]=v[i-1][j]+v[i][j-1]+v[i][j]-v[i-1][j-1];    
}

inline ll sum(ll x1,ll x2,ll y1,ll y2){
    return v[x2][y2]-v[x1-1][y2]-v[x2][y1-1]+v[x1-1][y1-1];
}

void dp(){
    for(ll i=1;i<=n;++i){
        f[i][i]=1;
        if(sum(i,i,i,i)==1){
            putchar('0');
            putchar('\n');
            return;
        }
    }
    for(ll len=2;len<=n;++len)
        for(ll l=1;l<=n-len+1;++l){
            ll r=l+len-1;
            if(!sum(l,l,l+1,r)) f[l][r]=(f[l][r]+f[l+1][r])%mod;
            if(!sum(l+1,r,l,l)) f[l][r]=(f[l][r]+f[l+1][r])%mod;
            for(ll k=l;k<=r;++k)
                if((!sum(k+1,r,l,k))&&(!sum(l,l,l+1,k)))
                    f[l][r]=(f[l][r]+f[l+1][k]*f[k+1][r])%mod;
        }
    printf("%lld\n",f[1][n]);   
}

int main(){
    t=rd();
    while(t--){init();dp();}
    return 0; 
}

Guess you like

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