SOl p8461
考虑:
-
源点向每个开始区间
i 连边,容量为1 ,费用为a_i 。 -
每个开始区间
i 向数轴上对应在区间[sl_i,sr_i] 的点连边,容量为1 ,费用为0 。 -
数轴上的
i 向i+1 连边,容量为1 ,费用为1 。 -
数轴上每个在区间
[el_j,er_j] 的点向对应结束区间j 连边,容量为1 ,费用为0 。 -
每个结束区间
j 向汇点连边,容量为1 ,费用为b_j 。
建出来的网络流模型应该是这样的:
这样建图,一个开始区间
跑最大费用最大流(把费用取相反数然后按照最小费用最大流做),复杂度
令「关键点」集合
证明就是如果左端点选择了不属于
如果
右端点同理。
所以数轴上只需要保留
struct Edge {
int to, nxt, f; ll c;
} e[int (2e5) + 7];
void Addedge (int u, int v, int f, ll c) {
++ cnt;
e[cnt].to = v, e[cnt].nxt = hd[u], e[cnt].f = f, e[cnt].c = c;
hd[u] = cnt;
}
namespace SSP {
int pre[N], vis[N];
ll dis[N], f[N];
int ans; ll cst;
void Update () {
ans += f[t], cst += dis[t] * f[t];
int now = t;
while (now != s) {
int _ = pre[now];
e[_].f -= f[t], e[_ ^ 1].f += f[t];
now = e[_ ^ 1].to;
}
}
int BF () {
queue <int> q;
q.push (s);
F (i, 0, len) dis[rk[i]] = inf;
F (i, 0, len) vis[rk[i]] = 0;
dis[s] = 0ll;
vis[s] = 1;
f[s] = inf;
while (! q.empty ()) {
int u = q.front (); q.pop ();
vis[u] = 0;
for (int i = hd[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
ll fl = e[i].f, c = e[i].c;
if (fl > 0 && c + dis[u] < dis[v]) {
dis[v] = c + dis[u];
f[v] = min (f[u], fl);
pre[v] = i;
if (! vis[v]) {
vis[v] = 1;
q.push (v);
}
}
}
}
return (dis[t] != inf);
}
void EK () {
while (BF ()) {
Update ();
}
}
}
#define AE(u,v,f,c) Addedge (u, v, f, c); Addedge (v, u, 0, -(c));
int main() {
IOS
cin >> n >> m1 >> m2;
len = 2; rk[0] = s, rk[1] = t, rk[2] = _s;
F (i, 0, N - 1) hd[i] = -1;
F (i, 1, m1) cin >> sl[i] >> sr[i];
F (i, 1, m2) cin >> el[i] >> er[i];
F (i, 1, m1) qwq[++ _n] = sl[i]; F (i, 1, m1) qwq[++ _n] = sr[i];
F (i, 1, m2) qwq[++ _n] = el[i]; F (i, 1, m2) qwq[++ _n] = er[i];
sort (qwq + 1, qwq + _n + 1);
F (i, 1, _n) mp[qwq[i]] = 1;
F (i, 1, m1) cin >> a[i]; F (i, 1, m2) cin >> b[i];
AE (s, _s, n, 0);
F (i, 1, m1) {
-- pos;
AE (_s, pos, 1, -a[i]);
rk[++ len] = pos;
F (j, sl[i], sr[i])
if (mp[j]) {AE (pos, j, 1, 0);}
}
F (i, 1, m2) {
-- pos;
AE (pos, t, 1, -b[i]);
rk[++ len] = pos;
F (j, el[i], er[i])
if (mp[j]) {AE (j, pos, 1, 0);}
}
F (i, 1, _n) rk[++ len] = qwq[i];
F (i, 1, _n - 1) {
AE (qwq[i], qwq[i + 1], 1, qwq[i] - qwq[i + 1]);
}
SSP :: EK ();
if (SSP :: ans != n) {
cout << -1 << '\n'; return 0;
} else {
cout << - SSP::cst << '\n'; return 0;
}
}