1748E Yet Another Array Counting Problem

1748E Yet Another Array Counting Problem

目录

  • 1748E Yet Another Array Counting Problem
    • 题目大意:
    • 做法
    • code

题目传送门

题目大意:

现在有一个长度为 n n n的数组 a a a , 现在你要找到一个数组 b b b的每一个数都 < = m <= m <=m 使得在 n n n中的任意区间 [ l , r ] [l , r] [l,r]满足 m a x i = l r a i = m a x i = l r b i max_{i = l} ^ ra_i = max_{i = l} ^ rb_i maxi=lrai=maxi=lrbi 求方案数 $ mod 1e9 + 7$

做法

d p p o s , i dp_{pos , i} dppos,i表示 p o s pos pos作为左边最大值的位置,且 b p o s < = i b_{pos} <= i bpos<=i 的方案数
显然 d p p o s , i = ∑ j = 1 i d p l p o s , j − 1 ∗ d p r p o s , j dp_{pos , i} = \sum _{j = 1} ^ i dp_{lpos , j - 1} * dp_{rpos , j} dppos,i=j=1idplpos,j1dprpos,j
可以用线段树维护 l p o s 、 r p o s lpos、rpos lposrpos

code

#include
#define fu(x , y , z) for(int x = y ; x <= z ; x ++) 
#define LL long long 
using namespace std;
const int N = 2e5 + 5;
const LL mod = 1e9 + 7;
vector<LL> dp[N];
int a[N] , n , m , rt , tr[N << 2];
int read () {
    int val = 0 , fu = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') fu = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        val = val * 10 + (ch - '0');
        ch = getchar ();
    }
    return val * fu;
}
void build (int p , int l , int r) {
    if (l == r) {
        tr[p] = l;
    }
    else {
        int mid = l + r >> 1 , ll = p << 1 , rr = (p << 1) + 1;
        build (ll , l , mid) , build (rr , mid + 1 , r);
        if (a[tr[ll]] >= a[tr[rr]]) {
            tr[p] = tr[ll];
        }
        else 
            tr[p] = tr[rr];
    }
}
int query (int p , int l , int r , int L , int R) {
    if (L <= l && R >= r) {
        return tr[p];
    }
    else {
        int mid = l + r >> 1 , ans1 = 0 , ans2 = 0 , ll = p << 1 , rr = (p << 1) + 1;
        if (L <= mid) 
            ans1 = query (ll , l , mid , L , R);
        if (mid < R)
            ans2 = query (rr , mid + 1 , r , L , R);
        return a[ans1] >= a[ans2] ? ans1 : ans2;
    }
}
int dfs (int l , int r) {
    if (l > r) 
        return -1;
    if (l == r) {
        fu(i , 1 , m) 
            dp[l][i] = i;
        return l;
    }
    int id = query (1 , 1 , n , l , r);
    int ll = dfs (l , id - 1) , rr = dfs (id + 1 , r);
    if (ll == -1)
        fu(i , 1 , m)
            dp[id][i] = (dp[rr][i] + dp[id][i - 1]) % mod;
    else if (rr == -1) 
        fu(i , 1 , m) 
            dp[id][i] = (dp[ll][i - 1] + dp[id][i - 1]) %mod;
    else 
        fu(i , 1 , m) 
            dp[id][i] = (dp[ll][i - 1] * dp[rr][i] % mod + dp[id][i - 1]) % mod;
    return id;
}
int main () {
    int T = read ();
    while (T --) {
        n = read () , m = read ();
        fu(i , 1 , n) {
            a[i] = read ();
            dp[i].clear ();
            dp[i].resize(m + 1);
        }
        build (1 , 1 , n);
        rt = dfs (1 , n);
        printf ("%lld\n" , dp[rt][m]);
    }
    return 0;
} 

你可能感兴趣的:(dp,dfs,分治,深度优先,算法)