现在有一个长度为 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,j−1∗dprpos,j
可以用线段树维护 l p o s 、 r p o s lpos、rpos lpos、rpos
#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;
}