zoukankan      html  css  js  c++  java
  • 【费用流】loj#545. 「LibreOJ β Round #7」小埋与游乐场

    好像现在看来这个缩点的思路挺清晰啊

    题目描述

    有两个非负整数组成的可重集合 $A$ 和 $B$。

    现在你可以对 $A$ 中至多 $k$ 个元素进行操作。操作方法为:设你准备操作且未被操作过的 $A$ 中的元素是 $a$,你可以在 $B$ 中选取任意一个元素 $b$,将 $a$ 修改为 $aoplus b$(这里 $oplus$ 表示二进制按位异或),然后从 $B$ 中删去 $b$。

    最终,你要使 $A$ 中所有元素的 $mathrm{lowbit}$ 之和最小。正整数的 $mathrm{lowbit}$ 定义为其二进制最低非零位的值,$0$ 的 $mathrm{lowbit}$ 规定为 $0$,例如 $mathrm{lowbit}(0)=0,mathrm{lowbit}(1)=1,mathrm{lowbit}(24)=8$。形式化地有:

    $mathrm{lowbit}(x)= egin{cases} max({2^k:kin mathbb{N},2^k|x}) & xin mathbb{N}^+\ 0 & x=0 end{cases}$

    (其中 $|$ 表示整除)

    你需要求出操作后 $A$ 中所有元素的 $mathrm{lowbit}$ 之和的可能的最小值。

    输入格式

    第一行一个整数 $n$ 表示 $A$ 的元素个数。
    接下来一行 $n$ 个整数 ${a_i}$ 表示 $A$ 中元素。
    接下来一行一个整数 $m$ 表示 $B$ 的元素个数。
    接下来一行 $m$ 个整数 ${b_i}$ 表示 $B$ 中元素。
    接下来一行一个整数 $k$。

    输出格式

    输出一行一个整数 $S$ 表示操作后 $A$ 中所有元素的 $mathrm{lowbit}$ 之和的可能的最小值。

    数据范围

    对于所有数据,$1le n,m,kle 1.2 imes 10^6,0le a_i,b_ile 10^9$


    题目分析

    注意到只有两种类型操作是有效的:

    1. $lowbit(a_i) > lowbit(b_i)$
    2. $a_i=b_i$

    那么对于$lowbit$相同的点,实际上可以作为等价类考虑。首先预处理出$cnt_{a/b}$表示${{a/b}_i}$中的具有相同lowbit的数目;$cnt_c$表示$a_i$与$b_i$的具有相同lowbit的交。

    连边则是在$a_i$和$b_j(j  < i)$间连$(INF,2^{i-1}-2^{j-1})$的边;在$a_i$和$b_i$之间连$(cnt_{ci},2^{i-1})$的边;$S$向$a_i$连$(cnt_{ai},0)$的边;$b_i$向$T'$连$(cnt_{bi},0)$的边;最后$T'$向$T$连$(k,0)$的边限制流量。

    由于所求的是最小值,那么对于这张图应该跑最大费用可行流。写的时候没带脑子地直接写了个最大费用最大流

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 const int maxn = 1200035;
     4 const int maxm = 200035;
     5 const int maxNode = 2035;
     6 const ll INF = 2e9;
     7 
     8 struct Edge
     9 {
    10     int u,v,f,c,dis;
    11     Edge(int a=0, int b=0, int c=0, int d=0, int e=0):u(a),v(b),f(c),c(d),dis(e) {}
    12 }edges[maxm];
    13 int n,m,K,S,T,befT;
    14 int edgeTot,head[maxNode],nxt[maxm],bck[maxNode],flw[maxNode];
    15 int a[maxn],b[maxn],cnta[35],cntb[35],cntc[35];
    16 bool inq[maxNode];
    17 ll ans,dis[maxNode];
    18 
    19 int read()
    20 {
    21     char ch = getchar();
    22     int num = 0, fl = 1;
    23     for (; !isdigit(ch); ch=getchar())
    24         if (ch=='-') fl = -1;
    25     for (; isdigit(ch); ch=getchar())
    26         num = (num<<1)+(num<<3)+ch-48;
    27     return num*fl;
    28 }
    29 int lowbit(int x)
    30 {
    31     if (!x) return 0;
    32     return log2(x&-x)+1;
    33 }
    34 void addedge(int u, int v, int c, int dis)
    35 {
    36     edges[edgeTot] = Edge(u, v, 0, c,  dis), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
    37     edges[edgeTot] = Edge(v, u, 0, 0, -dis), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
    38 }
    39 void maxFlow()
    40 {
    41     for (;;)
    42     {
    43         std::queue<int> q;
    44         memset(flw, 0, sizeof flw);
    45         memset(bck, 0, sizeof bck);
    46         memset(dis, -0x3f3f3f3f, sizeof dis);
    47         q.push(S), flw[S] = INF, dis[S] = 0;
    48         for (int tmp; q.size(); )
    49         {
    50             tmp = q.front(), q.pop(), inq[tmp] = 0;
    51             for (int i=head[tmp]; i!=-1; i=nxt[i])
    52             {
    53                 int v = edges[i].v;
    54                 if (dis[tmp]+edges[i].dis > dis[v]&&edges[i].f < edges[i].c){
    55                     bck[v] = i, dis[v] = dis[tmp]+edges[i].dis;
    56                     flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
    57                     if (!inq[v]) inq[v] = 1, q.push(v);
    58                 }
    59             }
    60         }
    61         if (dis[T] < 0) return;
    62         for (int i=T; i!=S; i=edges[bck[i]].u)
    63             edges[bck[i]].f += flw[T], edges[bck[i]^1].f -= flw[T];
    64         ans -= dis[T]*flw[T];
    65     }
    66 }
    67 int main()
    68 {
    69     memset(head, -1, sizeof head);
    70     n = read();
    71     for (int i=1, val; i<=n; i++)
    72         a[i] = read(), val = lowbit(a[i]), ++cnta[val], ans += val?(1ll<<(val-1)):0;
    73     m = read();
    74     for (int i=1; i<=m; i++)
    75         b[i] = read(), ++cntb[lowbit(b[i])];
    76     std::sort(a+1, a+n+1);
    77     std::sort(b+1, b+m+1);
    78     for (int i=1, j=1, p=1, q=1; i<=n; i=j+1)
    79     {
    80         for (j = i; j!=n&&a[j]==a[j+1]; ++j);
    81         for (; p < m&&b[p] < a[i]; ++p);
    82         for (q = p; p <= m&&b[p]==a[i]; ++p);
    83         cntc[lowbit(a[i])] += std::min(j-i+1, p-q);
    84     }
    85     K = read(), S = 32*2+10, T = S+1, befT = T+1;
    86     addedge(befT, T, K, 0);
    87     for (int i=1; i<=31; i++)
    88     {
    89         addedge(S, i, cnta[i], 0);
    90         addedge(i+32, befT, cntb[i], 0);
    91         addedge(i, i+32, cntc[i], 1<<(i-1));
    92         for (int j=1; j<i; j++)
    93             addedge(i, j+32, INF, (1<<(i-1))-(1<<(j-1)));
    94     }
    95     maxFlow();
    96     printf("%lld
    ",ans);
    97     return 0;
    98 }

    END

  • 相关阅读:
    SpringKafka——消息监听
    RabbitMQ(八)线程池消费
    RabbitMQ(七)延迟队列
    window计划任务 0x1
    获取网页URL地址及参数等的两种方法(js和C#)
    HttpWebRequest的偶尔请求超时问题
    用HTML、CSS、JS制作圆形进度条(无动画效果)
    批量关联update
    仅仅 IE8 有效的 CSS hack 写法
    SqlServer关闭与启用标识(自增长)列
  • 原文地址:https://www.cnblogs.com/antiquality/p/10473335.html
Copyright © 2011-2022 走看看