• 「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;
    }
    
  • 相关阅读:
    The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make s
    ScrollView 定位
    Fragment获取Activity,Activity获取Fragment
    Popupwindow全屏问题
    bzoj千题计划310:bzoj5285: [Hnoi2018]寻宝游戏(思维题+哈希)
    bzoj千题计划309:bzoj4332: JSOI2012 分零食(分治+FFT)
    2016vijos 1-3 兔子的晚会(生成函数+倍增FWT)
    bzoj千题计划308:bzoj4589: Hard Nim(倍增FWT+生成函数)
    bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋
    cdqz2017-test10-加帕里图书馆(区间DP & 简单容斥)
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/12983167.html
Copyright © 2020-2023  润新知