題目鏈接:HDU3842
題目大意
有
若你一開始有
題目分析
1. 斜率優化DP,先對時間排序。
2. 設
3. 由於
上代碼
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long double DB;
typedef long long LL;
const LL N = 1e5 + 10;
const LL INF = 0x3f3f3f3f;
LL n;
inline LL read() {
char ch;
LL ans = 0, neg = 1LL;
while (!isdigit(ch = getchar()))
if (ch == '-') neg = -1;
while (isdigit(ch))
ans = ans * 10 + ch - '0', ch = getchar();
return ans * neg;
}
struct Mac {
LL D, P, R, G;
inline void input() {
D = read(), P = read(), R = read(), G = read();
}
inline bool operator < (const Mac &a) const {
return D < a.D;
}
} mac[N];
LL root, cnt;
LL fa[N], ch[N][2], size[N], plc[N];
#define lc(a) (ch[a][0])
#define rc(a) (ch[a][1])
#define csk(a) (ch[fa[a]][1] == a)
#define makeLink(a, b, c) fa[ch[a][c] = b] = a
#define isRoot(a) (ch[fa[a]][0] != a && ch[fa[a]][1] != a)
inline void update(LL a) {
size[a] = 1;
if (lc(a)) size[a] += size[lc(a)];
if (rc(a)) size[a] += size[rc(a)];
}
inline void rotate(LL a) {
LL c = csk(a), f = fa[a];
makeLink(f, ch[a][c ^ 1], c);
if (isRoot(f)) fa[a] = fa[f];
else makeLink(fa[f], a, csk(f));
makeLink(a, f, c ^ 1), update(f), update(a);
}
void splay(LL a, LL dst) {
while (fa[a] != dst) {
if (fa[fa[a]] != dst) {
if (csk(fa[a]) == csk(a)) rotate(fa[a]);
else rotate(a);
} rotate(a);
}
if (!fa[a]) root = a;
}
inline LL getPre(LL a) {
splay(a, 0), a = lc(a);
while (rc(a)) a = rc(a);
return a;
}
inline LL getNxt(LL a) {
splay(a, 0), a = rc(a);
while (lc(a)) a = lc(a);
return a;
}
inline LL getVal(LL a) {
if (a == 1) return 0;
if (a == 2) return INF;
return mac[plc[a]].G;
}
inline LL insert(LL a) {
LL id = ++cnt; plc[id] = a;
LL tmp = root;
while (!fa[id]) {
if (getVal(tmp) <= getVal(id))
if (rc(tmp)) tmp = rc(tmp);
else makeLink(tmp, id, 1);
else
if (lc(tmp)) tmp = lc(tmp);
else makeLink(tmp, id, 0);
}
while (update(tmp), !isRoot(tmp)) tmp = fa[tmp];
return id;
}
inline void delett(LL a) {
LL pre = getPre(a), nxt = getNxt(a);
splay(pre, 0), splay(nxt, root);
lc(nxt) = 0, update(nxt), update(pre);
}
LL dp[N];
#define ff(a) (dp[a] - mac[a].D * mac[a].G - mac[a].G + mac[a].R)
inline DB calcK(LL a, LL b) {
// cout << ff(a) << " " << ff(b) << endl;
if (mac[a].G == mac[b].G)
return ff(a) - ff(b) > 0 ? -INF : INF;
return (DB)(ff(a) - ff(b)) / (mac[a].G - mac[b].G);
}
inline bool judge(LL a) {
LL pre = getPre(a), nxt = getNxt(a);
if (pre == 1 || nxt == 2) return true;
if (calcK(plc[pre], plc[a]) <= calcK(plc[a], plc[nxt]))
return false;
return true;
}
int main() {
LL T = 0;
while (++T) {
memset(fa, 0, sizeof(fa));
memset(ch, 0, sizeof(ch));
n = read(), dp[0] = read();
mac[n + 1].D = read() + 1;
mac[n + 1].P = mac[n + 1].R = mac[n + 1].G = 0;
if (!n && !dp[0] && mac[n + 1].D == 1) break;
cnt = 2, makeLink(1, 2, 1), update(root = 1), insert(0);
printf("Case %lld: ", T);
for (LL i = 1; i <= n; i++) mac[i].input();
sort(mac + 1, mac + n + 2);
for (LL i = 1; i <= n + 1; i++) {
while (size[root] > 3) {
LL a = getNxt(1), b = getNxt(a);
if (calcK(plc[a], plc[b]) >= -mac[i].D) delett(a);
else break;
}
LL tmp = plc[getNxt(1)];
dp[i] = ff(tmp) + mac[i].D * mac[tmp].G - mac[i].P;
// cout << i << " " << tmp << endl;
if (dp[i] < 0) continue;
if (tmp = insert(i), judge(tmp)) {
LL now = 0;
while (plc[now = getPre(tmp)] && !judge(now))
delett(now);
while (plc[now = getNxt(tmp)] && !judge(now))
delett(now);
} else delett(tmp);
}
printf("%lld\n", dp[n + 1]);
}
return 0;
}
以上