Live2D

Solution -「NEERC 2016」Delight for a Cat 的一个尝试

Description

  Link.

  给定 n,k,ms,me 和两个长为 n 的序列 {s},{e}, 选择一个 S[1,n]N, 满足 l[1,nk+1], i=ll+k1[iS][ms,kme], 并最大化 i=1n([iS]si+[iS]ei).

  n103.

Solution

  这里一个机械化方法的尝试, 没写代码是因为不可告人的原因. (

  我们想求

(1)maxi=1nei+i=1n(siei)(xixi1)s.t.x0=0xixi1(i>0)xi1xi1(i>0)xixikms(ik)xikximek(ik)

  先忽略 x0=0 这个约束. 从现在起, 我们停止思考, 直接去套这个 trick. 通过足够大的代价 I 间接限定 :

(1)maxi=1nei+i=1n(sisi+1ei+ei+1)xii=1nmax{xi1xi,0}Ii=1nmax{xixi11,0}Ii=knmax{ms+xikxi,0}Ii=knmax{mek+xixik,0}I.

注意到这个形式满足模型

minubuxu+v,ucuvmax{0,xvxuwuv},

因此可以直接翻译为费用流建图. 先取个负把 max 变成 min, 令 bi=si+1si+eiei+1, 流网络 G=(V,E) 建图如下:

V={S,T}{1,2,,n},E={S,i,bi,0bi>0}{u,T,bi,0bi<0}{i,i1,I,0}{i1,i,I,1}{i,ik,I,ms}{ik,i,I,kme}.

设最小费用为 c, 对应的解集 {x0..n}. 注意此时可能有 x00, 所以需要令 xixix0 并得到实际的最小费用 c, 则 i=1nei+c 就是答案, {x0..n} 的差分就是方案. 复杂度为 O(Dinic(n,5n)).

  不过 ... 求这个解集 {x0..n} 并不太容易. 神 crashed 称可以将残量网络上的 fuv 对偶回原线规, 然后根据互松弛定理得到关于 x 的取等条件, 最后建差分约束解出 x. 现在你知道我没有写代码的原因啦!

Code

  放一下传统建图的代码, 直接读建图部分不难理解. 复杂度是一样的.

/*+Rainybunny+*/

#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)

typedef long long LL;
typedef std::pair<int, LL> PIL;
typedef std::pair<LL, int> PLI;
#define fi first
#define se second

const int MAXN = 1e3;
int n, k, ms, me, s[MAXN + 5], e[MAXN + 5];

namespace FG {

// #define POSITIVE_FLAG // determined if spfa is necessary.

const int MAXND = MAXN + 1, MAXEG = MAXN * 2 + 1;
const LL LINF = 1ll << 60;
int S, T, ecnt = 1, head[MAXND + 5], curh[MAXND + 5];
LL dis[MAXND + 5], hgt[MAXND + 5];
struct Edge { int to, flw, cst, nxt; } graph[MAXEG * 2 + 5];
bool instk[MAXND + 5];

inline void link(const int s, const int t, const int f, const int c) {
    // printf("%d %d %d,%d\n", s, t, f, c);
    graph[++ecnt] = { t, f, c, head[s] }, head[s] = ecnt;
    graph[++ecnt] = { s, 0, -c, head[t] }, head[t] = ecnt;
}

#ifndef POSITIVE_FLAG
inline bool spfa() {
    static std::queue<int> que;
    static bool inq[MAXND + 5];
    rep (i, S, T) dis[i] = LINF;
    dis[S] = 0, que.push(S);
    while (!que.empty()) {
        int u = que.front(); que.pop(), inq[u] = false;
        for (int i = head[u], v; i; i = graph[i].nxt) {
            if (graph[i].flw && dis[v = graph[i].to] > dis[u] + graph[i].cst) {
                dis[v] = dis[u] + graph[i].cst;
                if (!inq[v]) inq[v] = true, que.push(v);
            }
        }
    }
    return dis[T] != LINF;
}
#endif

inline bool dijkstra() {
    static std::priority_queue<PLI, std::vector<PLI>, std::greater<PLI>> heap;
    rep (i, S, T) hgt[i] += dis[i], dis[i] = LINF;
    heap.emplace(dis[S] = 0, S);
    while (!heap.empty()) {
        PLI p(heap.top()); heap.pop();
        if (p.fi != dis[p.se]) continue;
        for (int i = head[p.se], v; i; i = graph[i].nxt) {
            LL d = p.fi + graph[i].cst - hgt[v = graph[i].to] + hgt[p.se];
            if (graph[i].flw && d < dis[v]) heap.emplace(dis[v] = d, v);
        }
    }
    return dis[T] != LINF;
}

inline PIL augment(const int u, int iflw) {
    if (u == T) return { iflw, 0 };
    PIL ret(0, 0); instk[u] = true;
    for (int &i = curh[u], v; i; i = graph[i].nxt) {
        if (graph[i].flw && !instk[v = graph[i].to]
          && dis[v] == dis[u] + graph[i].cst - hgt[v] + hgt[u]) {
            PIL t(augment(v, std::min(iflw, graph[i].flw)));
            graph[i].flw -= t.fi, graph[i ^ 1].flw += t.fi;
            ret.fi += t.fi, iflw -= t.fi;
            ret.se += t.se + 1ll * graph[i].cst * t.fi;
            if (!iflw) break;
        }
    }
    if (ret.fi) instk[u] = false;
    return ret;
}

inline PIL dinic() {
    PIL ret(0, 0);
#ifdef POSITIVE_FLAG
    while (dijkstra()) {
#else
    for (spfa(); dijkstra();) {
#endif
        rep (i, S, T) curh[i] = head[i], instk[i] = false;
        PIL t(augment(S, 0x3f3f3f3f));
        ret.fi += t.fi, ret.se += t.se;
    }
    return ret;
}

} // namespace FG.

int main() {
    scanf("%d %d %d %d", &n, &k, &ms, &me);
    rep (i, 1, n) scanf("%d", &s[i]);
    rep (i, 1, n) scanf("%d", &e[i]);
 
    FG::S = 0, FG::T = n + 1;
    rep (i, 1, n) FG::link(i, std::min(i + k, n + 1), 1, s[i] - e[i]);
    rep (i, 1, k - 1) FG::link(i, i + 1, k - ms, 0);
    rep (i, k, n) FG::link(i, i + 1, k - ms - me, 0);
    FG::link(FG::S, 1, k - ms, 0);

    LL ans = 0;
    rep (i, 1, n) ans += s[i];
    printf("%lld\n", ans - FG::dinic().se);
    rep (i, 1, n) putchar("ES"[FG::graph[i << 1].flw]);
    putchar('\n');
    return 0;
}

posted @   Rainybunny  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示