「CTSC2010」製品販売

「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;
}

おすすめ

転載: www.cnblogs.com/klauralee/p/11358663.html