「CTSC2010」製品販売
30ptsコストが右に流れます...
ライン上で100pts長いシミュレーションコストの流れ、(非常に単純な方法ではありません
GUGU区
オーダー\(M_Iは\)を表し\を(I-1〜Iに\ \) 前方側、\(M_Iが^ {「} \)の逆エッジを表します
\(C_I \)を表し\(iはI-1 \ \) 前縁、\(C_Iは^ {「} \)の逆エッジを表しを
列挙続い\(1、\ cdots、N \)
現在の列挙\(私は\) 、作る\(I \ RIGHTARROWトン\)フルフロー
两种决策:\(S \ RIGHTARROW J \ Jに+ 1 \ \ cdots \ iは\にする)または\(I \ LEFTARROW I + 1 \ LEFTARROW \ cdots \ LEFTARROW J \ LEFTARROW S \)
以下の式は、開始位置である\(J \) 。
第2の判定
順次列挙し、そうので(M_I + 1、\ cdots \ 、M_j \) 流れず、コスト(\ \ sum_ {K}は、^ = Iは、J 1コスト[C_k] \ + 1) 。
ための\(Iは\)順次押し上げられ、それが直接に可能である\(\ sum_ {k = 1 } ^ jのコスト[C_k] \) ソーティングをスキップ\(iはU || k個の\の当量 [k]を= = 0 \)ポイント、あなたは最高のを取ることができます。
最初の決定
現在の意思決定のために、もし片側\(C_k(J + 1 \当量のK \当量I)\) それはコストのマイナスので、トラフィックが\(コスト[C_k] + [M_k]費用\) 。
可能流量\(MIN(W [C_k])(\ \ GEQ。1)[C_K] W) 。
だから何を変換することができますの追加\(k個\)開始のための時間のこの時点で、([1、K-1] \)\の最初の決定のパス、場合\(C_k \)は、トラフィックが非常にすべてがあり、マイナス\(コスト[C_k] \) 、またはプラス\(コスト[M_k] \) 。
場合(C_k \)\ゼロに減少した流量、始める\([1、K-1 ] \) 最初の決定の経路プラス全て\(費用は[M_k] +コスト[C_k] \) 。
明らかにのために\(C_k \)の変更のみ2回実施されます。
具体的にそれを維持する方法について話...
AN1メンテナンスセグメントツリー\([C_x] W \)、AN2はに維持(J \)を\現在の列挙への出発点として(私は\)\コスト。
以下のため\(AN1 \)維持する\(MIN(W [C_x])(W [C_x] \ GEQ 1)\)は、便宜上、初期値に設定されている\(INF \)
最初の決定
AN2クエリ\([1、i]は\ ) の最小値である\(最小\) 、および位置探し\(K \)を。
AN1クエリ\([K + 1、I ] \) \(MINF \) = \(MIN(W [C_x])([C_x] W \ GEQ 1)\) 、その位置を見つけます。
可能なフロー\(フロー\)の\(MIN(U- [K]、D [I]、MINF)\) 。
AN1の\([K + 1、I ] \) 全てマイナス流れの\(U- [K] - =フロー、D [I] -フロー= \) 。
でAN1用(W [C_k] == 0 \ )\の点は、重量に設定する(INFを\)\、およびAN2における\([1、\ cdots、 K-1] \) ポイントプラス\ (コスト[M_k] +コスト[C_k] \) 。
もし\(U- [K] == 0 \) AN2に設けられ、\(K \)重み値\(INF \) 。
第2の判定
位置の開始\(K \)を、流量が可能である\(フロー=分(U- [K]、D [I])\) 。
最初AN1へ\([Iが+ 1、K] \)正しい(INF \)\が 0を指すように変更され、互いに素なセットをスキップしないで\(INF \)を指し示します。
次にAN1 \は([I + 1、K。] \)重量+ \(フロー\)、\ (U- [K] - =フロー、D [I] -フロー= \) 。
私は1 +次の点に列挙
\は、(i + 1 \) (場合AN2に加え\(U [I + 1] == 0 \)をするように設定されている(INF \)を\します)
AN2に、\([1、I] \)プラス\(W [C_ {I + 1}] \ GEQ 1 -COST [C_ {I + 1}]:?コスト[M_ {I + 1}] \)
実際には、あなたがAN1を見つけることができ、操作のAN2サポートが同じです
#include <bits/stdc++.h>
//#pragma GCC target("avx,avx2,sse4.2")
#define rep(q, a, b) for (int q = a, q##_end_ = b; q <= q##_end_; ++q)
#define dep(q, a, b) for (int q = a, q##_end_ = b; q >= q##_end_; --q)
#define mem(a, b) memset(a, b, sizeof a)
#define debug(a) cerr << #a << ' ' << a << "___" << endl
using namespace std;
// char buf[10000000], *p1 = buf, *p2 = buf;
#define Getchar() \
getchar() // p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++
void in(int &r) {
static char c;
r = 0;
bool flag(0);
while (c = Getchar(), c < 48) (c == '-') && (flag = 1);
do
r = (r << 1) + (r << 3) + (c ^ 48);
while (c = Getchar(), c > 47);
flag && (r = -r);
}
const int mn = 100005;
const int INF = 2e9;
int n, D[mn], U[mn], P[mn], M[mn], C[mn];
struct node {
int x, v;
bool operator<(const node &A) const { return v < A.v; }
} an1[mn];
struct segment_tree {
int at[mn << 2], addv[mn << 2], y_1, y_2, ad_v, minv[mn << 2];
void build(int o, int l, int r, int v) {
minv[o] = v, at[o] = l;
if (l == r)
return;
int mid = l + r >> 1;
build(o << 1, l, mid, v);
build(o << 1 | 1, mid + 1, r, v);
}
void maintain(int o) {
if (minv[o << 1] + addv[o << 1] < minv[o << 1 | 1] + addv[o << 1 | 1]) {
minv[o] = minv[o << 1] + addv[o << 1];
at[o] = at[o << 1];
} else {
minv[o] = minv[o << 1 | 1] + addv[o << 1 | 1];
at[o] = at[o << 1 | 1];
}
}
void change(int o, int l, int r, int adv) {
adv += addv[o];
if (l == r)
minv[o] = ad_v - adv;
else {
int mid = l + r >> 1;
if (y_1 <= mid)
change(o << 1, l, mid, adv);
else
change(o << 1 | 1, mid + 1, r, adv);
maintain(o);
}
}
void change(int x, int v) {
y_1 = x, ad_v = v;
change(1, 1, n, 0);
}
void modify(int o, int l, int r) {
if (y_1 <= l && r <= y_2)
addv[o] += ad_v;
else {
int mid = l + r >> 1;
if (y_1 <= mid)
modify(o << 1, l, mid);
if (y_2 > mid)
modify(o << 1 | 1, mid + 1, r);
maintain(o);
}
}
void add(int l, int r, int v) {
if (l > r)
return;
y_1 = l, y_2 = r, ad_v = v;
modify(1, 1, n);
}
int Min, At;
void ask(int o, int l, int r, int adv) {
adv += addv[o];
if (y_1 <= l && r <= y_2) {
if (minv[o] + adv < Min)
Min = minv[o] + adv, At = at[o];
return;
}
int mid = l + r >> 1;
if (y_1 <= mid)
ask(o << 1, l, mid, adv);
if (y_2 > mid)
ask(o << 1 | 1, mid + 1, r, adv);
}
int ask(int l, int r) {
if (l > r)
return INF;
y_1 = l, y_2 = r, Min = INF;
ask(1, 1, n, 0);
return Min;
}
} an[2];
int fa[mn];
int find(int x) { return !fa[x] ? x : fa[x] = find(fa[x]); }
signed main() {
freopen("product.in", "r", stdin);
freopen("product.out", "w", stdout);
in(n);
rep(q, 1, n) in(D[q]);
rep(q, 1, n) in(U[q]);
rep(q, 1, n) in(P[q]);
rep(q, 2, n) in(M[q]);
rep(q, 2, n) in(C[q]);
int sm = 0;
rep(q, 2, n) sm += C[q], an1[q] = { q, sm + P[q] };
sort(an1 + 2, an1 + n + 1);
int tp = 2;
an[0].build(1, 1, n, INF);
an[1].build(1, 1, n, 0);
long long ans = 0;
sm = 0;
rep(q, 1, n) {
an[1].add(1, q - 1, an[0].ask(q, q) > 1e9 ? M[q] : -C[q]);
sm += C[q];
an[1].change(q, U[q] ? P[q] : INF);
while (D[q]) {
while (tp <= n && (an1[tp].x <= q || !U[an1[tp].x])) ++tp;
if (tp > n || an[1].ask(1, q) <= an1[tp].v - sm) {
int v = an[1].ask(1, q);
int at = an[1].At, vl = an[0].ask(at + 1, q);
int lim = min(min(D[q], U[at]), vl);
ans += 1LL * lim * v;
while (vl == lim) {
int at1 = an[0].At;
an[1].add(1, at1 - 1, C[at1] + M[at1]);
an[0].change(at1, INF);
vl = an[0].ask(at + 1, q);
}
an[0].add(at + 1, q, -lim);
D[q] -= lim, U[at] -= lim;
if (!U[at])
an[1].change(at, INF);
} else {
int at = an1[tp].x;
int mid = at, lim = min(U[at], D[q]);
U[at] -= lim, D[q] -= lim;
while (find(mid) >= q + 1) {
an[0].change(find(mid), 0);
fa[find(mid)] = find(mid) - 1;
}
an[0].add(q + 1, at, lim);
ans += 1LL * lim * (an1[tp].v - sm);
}
}
}
printf("%lld\n", ans);
return 0;
}