Description
有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]。有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i],那么这个人就不洗车了。请给每家店指定一个价格,使得所有人花的钱的总和最大。
Solution
设fl,r,k
f
l
,
r
,
k
表示只考虑完全被包含于[l,r]
[
l
,
r
]
的区间、[l,r]
[
l
,
r
]
的最小值为k
k
时的最大利润。
那么枚举m∈[l,r]m∈[l,r],有:fl,r,k=maxfl,m−1,x+fm+1,r,y+suml,r,m,kk
f
l
,
r
,
k
=
max
f
l
,
m
−
1
,
x
+
f
m
+
1
,
r
,
y
+
s
u
m
l
,
r
,
m
,
k
k
其中x≥k,y≥k
x
≥
k
,
y
≥
k
,suml,r,m,k
s
u
m
l
,
r
,
m
,
k
表示完全被包含于[l,r]
[
l
,
r
]
的区间中跨过m
m
且cc大于等于k
k
<script type="math/tex" id="MathJax-Element-576">k</script>的区间有多少个。
直接转移即可。
Code
/************************************************
* Au: Hany01
* Date: Aug 28th, 2018
* Prob: BZOJ4380 POI2015 Myjnie
* Inst: Yali High School
************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(), a.end()
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read() {
static int _, __; static char c_;
for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
const int maxn = 53, maxm = 4003;
int n, m, a[maxm], b[maxm], c[maxm], ls[maxm], stk[maxm], top, cur, g[maxn][maxn][maxm], f[maxn][maxn][maxm], fp[maxn][maxn][maxm], gp[maxn][maxn][maxm], tot;
void print(int l, int r, int k) {
if (l > r) return;
if (l == r) printf("%d ", ls[gp[l][r][k]]);
else
print(l, fp[l][r][gp[l][r][k]] - 1, gp[l][r][k]),
printf("%d ", ls[gp[l][r][k]]),
print(fp[l][r][gp[l][r][k]] + 1, r, gp[l][r][k]);
}
int main()
{
#ifdef hany01
freopen("bzoj4380.in", "r", stdin);
freopen("bzoj4380.out", "w", stdout);
#endif
n = read(), m = read();
For(i, 1, m) a[i] = read(), b[i] = read(), c[i] = ls[i] = read();
sort(ls + 1, ls + 1 + m), tot = unique(ls + 1, ls + 1 + m) - ls - 1;
For(i, 1, m) c[i] = lower_bound(ls + 1, ls + 1 + tot, c[i]) - ls;
Fordown(l, n, 1) For(r, l, n) {
For(k, 1, tot) fp[l][r][k] = l;
For(p, l, r) {
top = 0;
For(i, 1, m) if (l <= a[i] && b[i] <= r && a[i] <= p && p <= b[i]) stk[++ top] = c[i];
sort(stk + 1, stk + 1 + top), cur = 0;
For(k, 1, tot) {
while (cur < top && stk[cur + 1] < k) ++ cur;
if (chkmax(f[l][r][k], g[l][p - 1][k] + g[p + 1][r][k] + (top - cur) * ls[k])) fp[l][r][k] = p;
}
}
Fordown(k, tot, 1) {
g[l][r][k] = f[l][r][k], gp[l][r][k] = k;
if (chkmax(g[l][r][k], g[l][r][k + 1])) gp[l][r][k] = gp[l][r][k + 1];
}
}
printf("%d\n", g[1][n][1]), print(1, n, 1);
return 0;
}