1748E Yet Another Array Counting Problem

1748E Yet Another Array Counting Problem


题目传送门

题目大意:

现在有一个长度为n的数组a , 现在你要找到一个数组b的每一个数都<=m 使得在n中的任意区间[l,r]满足maxi=lrai=maxi=lrbi 求方案数 mod1e9+7

做法

dppos,i表示pos作为左边最大值的位置,且bpos<=i 的方案数
显然dppos,i=j=1idplpos,j1dprpos,j
可以用线段树维护lposrpos

code

#include<bits/stdc++.h>
#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;
} 
posted @   2020fengziyang  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示