题目描述
题解
我们发现矩形是好做的,那么我们就把这个图形划分成若干的矩形。上下不太好搞的,所以我们根据上下来拆矩形。对序列建出笛卡尔树(小根堆),考虑一个点的贡献是其父亲到它的这一段长度内可以放的车,记 (f_{i,j}) 代表在 (i) 的子树内放 (j) 个车的方案数。首先先不考虑 (i) 的贡献,有 (f_{i,j}=sum_{k=0}^{j}f_{lson(i),k} imes f_{rson(i),k})。考虑 (i) 的贡献,即在一个 (n imes m) 的矩形内放 (k) 个点的方案数,容易算出是 ({n choose k} imes {m choose k} imes k!)。那么就简单了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 505;
const ll mod = 1e9 + 7;
struct treap{
int val, key, sz, son[2], fa;
}tr[MAXN];
int root;
int n, k;
int h[MAXN], stk[MAXN], top;
ll f[MAXN][MAXN], fac[1000005], inv[1000005], ifac[1000005];
ll C(ll i, ll j) {
if (i < 0 || j < 0 || i < j) return 0;
return fac[i] * ifac[j] % mod * ifac[i - j] % mod;
}
void dfs(int x) {
tr[x].sz = 1;
for (int i = 0; i < 2; i++) {
if (!tr[x].son[i]) continue;
tr[tr[x].son[i]].fa = x;
dfs(tr[x].son[i]);
tr[x].sz += tr[tr[x].son[i]].sz;
}
for (int j = 0; j <= k; j++) {
for (int w = 0; w <= j; w++) {
f[x][j] = (f[x][j] + f[tr[x].son[0]][w] * f[tr[x].son[1]][j - w] % mod) % mod;
}
}
for (int j = k; j >= 0; j--) {
for (int w = 1; w <= j; w++) {
f[x][j] = (f[x][j] + f[x][j - w] * fac[w] % mod * C(tr[x].sz - j + w, w) % mod * C(tr[x].key - tr[tr[x].fa].key, w) % mod) % mod;
}
}
}
int main() {
scanf("%d%d", &n, &k);
inv[0] = inv[1] = 1;
fac[0] = ifac[0] = 1;
for (int i = 2; i <= 1000000; i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
for (int i = 1; i <= 1000000; i++) fac[i] = fac[i - 1] * i % mod, ifac[i] = ifac[i - 1] * inv[i] % mod;
for (int i = 1; i <= n; i++) {
tr[i].val = i;
scanf("%d", &tr[i].key);
}
for (int i = 1; i <= n; i++) {
while (top > 0 && tr[stk[top]].key > tr[i].key) {
int lst = stk[top];
top--;
if (top && tr[stk[top]].key > tr[i].key) tr[stk[top]].son[1] = lst;
else tr[i].son[0] = lst;
}
stk[++top] = i;
}
while (top > 1) {
tr[stk[top - 1]].son[1] = stk[top];
top--;
}
root = stk[1];
f[0][0] = 1;
dfs(root);
printf("%lld
", f[root][k]);
return 0;
}
一种更加好写的笛卡尔树建立方法:
for (int i=1; i<=n; i++) {
while (top>0&&a[stk[top]]>a[i]) ls[i]=stk[top--];
if (top) rs[stk[top]]=i;
stk[++top]=i;
}
root=stk[1];