「NOI2019d1t3」序列

「NOI2019d1t3」序列

题目链接

(Description)

长度为 (n (n leq 10 ^ 6)) 的两个序列 (a, b),要求各选 (K (K leq n)) 个数满足条件:

至少有 (L (L leq K)) 个数在序列中的位置相同;

满足上述条件时,使得选出数的和最大。

输出最大的和。

(Solution)

显然可以费用流,模型如下:

(S - A_i (1, a_i))(A_i - B_i (1, 0))(B_i - R (1, b_i))(R - T (K, 0))

(A_i - P (1, 0))(P - Q (K - L, 0))(Q - B_i (1, 0))

如果 (P - Q) 未流满,先考虑它肯定最优;

如果流满,那么只有两种选择:

1.选位置相同的一对;
2.选 (A) 中的最大值 (A_i)(B)(A_j) 已经被选过的最大值 (B_j),反之同理。

如果某一对 (A_i)(B_i) 在两此不同的增广里被选择,就不占用 (P-Q) 的流量。

模拟上述过程即可。

时间复杂度:(O (T n log_2 n))

(Source)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 1e6 + 5;

int n, K, L;
int a[N], b[N];

typedef std::pair<int, int> pii;
std::priority_queue<pii> q1, q2, h1, h2, q;
int vis1[N], vis2[N];

void prep() {
    memset(vis1, 0, sizeof(vis1));
    memset(vis2, 0, sizeof(vis2));
    while (!q1.empty()) q1.pop();
    while (!q2.empty()) q2.pop();
    //printf("%d
", h1.size());
    while (!h1.empty()) h1.pop();
    while (!h2.empty()) h2.pop();
    while (!q.empty()) q.pop();
    for (int i = 1; i <= n; ++i) {
        q1.push(pii(a[i], i)), q2.push(pii(b[i], i));
        q.push(pii(a[i] + b[i], i));
    }
}

long long work() {
    long long ret = 0;
    int now = 0;
    for (int i = 1; i <= K; ++i) {
        if (now < K - L) {
            int u, v;
            while (!q1.empty()) {
                u = q1.top().second; q1.pop();
                if (!vis1[u])
                    break;
            }
            while (!q2.empty()) {
                v = q2.top().second; q2.pop();
                if (!vis2[v])
                    break;
            }
            if (u != v) {
                if (!vis2[u])
                    h2.push(pii(b[u], u));
                if (!vis1[v])
                    h1.push(pii(a[v], v));
            }
            if (vis2[u] && vis1[v])
                --now;
            else if (!vis2[u] && !vis1[v] && u != v)
                ++now;
            vis1[u] = vis2[v] = 1;
            ret += a[u] + b[v];
        } else {
            int u1 = 0, u2 = 0, s1 = 0;
            while (!q1.empty()) {
                u1 = q1.top().second;
                if (!vis1[u1])
                    break;
                q1.pop();
            }
            while (!h2.empty()) {
                u2 = h2.top().second;
                if (!vis2[u2])
                    break;
                h2.pop();
            }
            if (u2 && !vis2[u2])
                s1 = a[u1] + b[u2];

            int v2 = 0, v1 = 0, s2 = 0;
            while (!q2.empty()) {
                v2 = q2.top().second;
                if (!vis2[v2])
                    break;
                q2.pop();
            }
            while (!h1.empty()) {
                v1 = h1.top().second;
                if (!vis1[v1])
                    break;
                h1.pop();
            }
            if (v1 && !vis1[v1])
                s2 = a[v1] + b[v2];

            int w = 0, s3 = 0;
            while (!q.empty()) {
                w = q.top().second;
                if (!vis1[w] && !vis2[w])
                    break;
                q.pop();
            }
            if (!vis1[w] && !vis2[w])
                s3 = a[w] + b[w];

            //printf("%d %d  %d %d  %d
", u1, u2, v1, v2, w);
            //printf("%d %d %d
", s1, s2, s3);
            if (w && s3 > s1 && s3 > s2) {
                q.pop();
                vis1[w] = vis2[w] = 1;
                ret += s3;
            } else if (s1 >= s3 && (s1 > s2 || (s1 == s2 && vis2[u1] > vis1[v2]))) {
                q1.pop(), h2.pop();
                vis1[u1] = 1, vis2[u2] = 1;
                if (vis2[u1])
                    --now;
                else
                    h2.push(pii(b[u1], u1));
                ret += s1;
            } else {
                //printf("%d
", h1.size());
                //printf("%d %d %d
", s1, s2, s3);
                q2.pop(), h1.pop();
                vis2[v2] = 1, vis1[v1] = 1;
                if (vis1[v2])
                    --now;
                else
                    h1.push(pii(a[v2], v2));
                ret += s2;
            }

        }
        //printf("%d %d
", u, v);
    }
    return ret;
}

int main() {
    //freopen("in", "r", stdin);
    //freopen("out2", "w", stdout);
    int tim = in();
    while (tim--) {
        n = in(), K = in(), L = in();
        for (int i = 1; i <= n; ++i)
            a[i] = in();
        for (int i = 1; i <= n; ++i)
            b[i] = in();
        prep();
        printf("%lld
", work());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/12983167.html