#2093. 「ZJOI2016」线段树(区间dp+整体思想)
题解:
-
我想这题时卡死在枚举每个点求答案,结果最优也只能\(O(n^4)\),要多从整体看。
-
考虑对整体来做,枚举\(x\),表示求\(\le x\)的方案数(经过尝试得到这个好算),\(x\)可以是离散后的,转换真正的答案显然。
-
考虑大于\(x\)的数把序列分成了若干段,对每一段做dp\(f[i][u][v]\)表示\(i\)步后\(a[u-1]>x,a[v+1]>x,a[u..v]\le x\)的方案数。
-
转移显然。
-
最后给\(Ans[t][\le x] += f[q][u][v] (t\in[u,v])\)即可。
-
这个因为随机大概是\(O(n^3 *log~n)\)
-
考虑拆式子,设离散后是\(d[1..d0]\),那么真正答案是\(\sum_{i=1}^{d0} (\le d[i] - \le d[i-1]方案数)*d[i]\)
-
\(=\sum_{i=1}^{d0-1} (\le d[i]方案数)*(d[i+1]-d[i])+(\le d[d0])*d[d0]\)
-
把这个作为dp的初值即可\(O(n^3)\)。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 1e9 + 7;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
const int N = 405;
ll c[N][N];
ll c2[N];
int n, q;
ll a[N];
ll d[N], d0;
ll b[N][N];
ll e[N], e0;
ll f[2][N][N]; int o;
ll ans[N];
int main() {
fo(i, 0, 400) {
c[i][0] = 1;
fo(j, 1, i) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
c2[i] = i * (i + 1) / 2;
}
scanf("%d %d", &n, &q);
fo(i, 1, n) scanf("%lld", &a[i]), d[++ d0] = a[i];
sort(d + 1, d + d0 + 1);
d0 = unique(d + 1, d + d0 + 1) - (d + 1);
fo(i, 1, d0) {
e0 = 0;
fo(j, 1, n) if(a[j] > d[i])
e[++ e0] = j;
e[0] = 0; e[e0 + 1] = n + 1;
fo(j, 1, e0 + 1) {
int x = e[j - 1], y = e[j];
if(x + 1 < y) {
ll v = i == d0 ? d[i] : (d[i] - d[i + 1]);
f[o][x + 1][y - 1] = (f[o][x + 1][y - 1] + v) % mo;
}
}
}
fo(i, 1, q) {
fo(x, 1, n) fo(y, x, n) {
f[!o][x][y] = f[o][x][y] * (c2[x - 1] + c2[n - y] + c2[y - x + 1]) % mo;
}
fo(x, 1, n) {
ll s = 0;
fd(y, n, x) {
f[!o][x][y] = (f[!o][x][y] + s) % mo;
s = (s + f[o][x][y] * (n - y)) % mo;
}
}
fo(y, 1, n) {
ll s = 0;
fo(x, 1, y) {
f[!o][x][y] = (f[!o][x][y] + s) % mo;
s = (s + f[o][x][y] * (x - 1)) % mo;
}
}
o = !o;
}
fo(x, 1, n) fo(y, x, n)
fo(i, x, y) ans[i] = (ans[i] + f[o][x][y]) % mo;
fo(i, 1, n) {
ans[i] = (ans[i] % mo + mo) % mo;
pp("%lld ", ans[i]);
}
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址