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

题目描述

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

现在你可以对 $A$ 中至多 $k$ 个元素进行操作。操作方法为:设你准备操作且未被操作过的 $A$ 中的元素是 $a$,你可以在 $B$ 中选取任意一个元素 $b$,将 $a$ 修改为 $a\oplus 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)= \begin{cases} \max(\{2^k:k\in \mathbb{N},2^k|x\}) & x\in \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}$ 之和的可能的最小值。

数据范围

对于所有数据,$1\le n,m,k\le 1.2\times 10^6,0\le a_i,b_i\le 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)$的边限制流量。

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

 #include<bits/stdc++.h>
typedef long long ll;
const int maxn = ;
const int maxm = ;
const int maxNode = ;
const ll INF = 2e9; struct Edge
{
int u,v,f,c,dis;
Edge(int a=, int b=, int c=, int d=, int e=):u(a),v(b),f(c),c(d),dis(e) {}
}edges[maxm];
int n,m,K,S,T,befT;
int edgeTot,head[maxNode],nxt[maxm],bck[maxNode],flw[maxNode];
int a[maxn],b[maxn],cnta[],cntb[],cntc[];
bool inq[maxNode];
ll ans,dis[maxNode]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
int lowbit(int x)
{
if (!x) return ;
return log2(x&-x)+;
}
void addedge(int u, int v, int c, int dis)
{
edges[edgeTot] = Edge(u, v, , c, dis), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
edges[edgeTot] = Edge(v, u, , , -dis), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
}
void maxFlow()
{
for (;;)
{
std::queue<int> q;
memset(flw, , sizeof flw);
memset(bck, , sizeof bck);
memset(dis, -0x3f3f3f3f, sizeof dis);
q.push(S), flw[S] = INF, dis[S] = ;
for (int tmp; q.size(); )
{
tmp = q.front(), q.pop(), inq[tmp] = ;
for (int i=head[tmp]; i!=-; i=nxt[i])
{
int v = edges[i].v;
if (dis[tmp]+edges[i].dis > dis[v]&&edges[i].f < edges[i].c){
bck[v] = i, dis[v] = dis[tmp]+edges[i].dis;
flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
if (!inq[v]) inq[v] = , q.push(v);
}
}
}
if (dis[T] < ) return;
for (int i=T; i!=S; i=edges[bck[i]].u)
edges[bck[i]].f += flw[T], edges[bck[i]^].f -= flw[T];
ans -= dis[T]*flw[T];
}
}
int main()
{
memset(head, -, sizeof head);
n = read();
for (int i=, val; i<=n; i++)
a[i] = read(), val = lowbit(a[i]), ++cnta[val], ans += val?(1ll<<(val-)):;
m = read();
for (int i=; i<=m; i++)
b[i] = read(), ++cntb[lowbit(b[i])];
std::sort(a+, a+n+);
std::sort(b+, b+m+);
for (int i=, j=, p=, q=; i<=n; i=j+)
{
for (j = i; j!=n&&a[j]==a[j+]; ++j);
for (; p < m&&b[p] < a[i]; ++p);
for (q = p; p <= m&&b[p]==a[i]; ++p);
cntc[lowbit(a[i])] += std::min(j-i+, p-q);
}
K = read(), S = *+, T = S+, befT = T+;
addedge(befT, T, K, );
for (int i=; i<=; i++)
{
addedge(S, i, cnta[i], );
addedge(i+, befT, cntb[i], );
addedge(i, i+, cntc[i], <<(i-));
for (int j=; j<i; j++)
addedge(i, j+, INF, (<<(i-))-(<<(j-)));
}
maxFlow();
printf("%lld\n",ans);
return ;
}

END

【费用流】loj#545. 「LibreOJ β Round #7」小埋与游乐场的更多相关文章

  1. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  2. [LOJ#530]「LibreOJ β Round #5」最小倍数

    [LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...

  3. [LOJ#516]「LibreOJ β Round #2」DP 一般看规律

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  4. [LOJ#515]「LibreOJ β Round #2」贪心只能过样例

    [LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...

  5. [LOJ#525]「LibreOJ β Round #4」多项式

    [LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...

  6. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

  7. [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)

    [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...

  8. loj #547. 「LibreOJ β Round #7」匹配字符串

    #547. 「LibreOJ β Round #7」匹配字符串   题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...

  9. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

随机推荐

  1. python 合并两个文件并将合并内容保存在另一个文件中

    简单地文件合并方法 思路如下: 分别读取两个文件中的内容,并将其保存在一个列表中,将列表通过join()函数转为字符,并将新字符保存在新的文件中. 其中,test1.txt中的内容为: test2.t ...

  2. ADO学途 one day

    博主在第一个demo的困苦中,略得一些见解,需要的伙伴可以get下 刚开始先创建一个程序的前端,这样对自己要实现的功能有一个直观的了解.分三 步:首先1.创建一个windows窗体.拖控件使程序接近真 ...

  3. CCPC吉林站

    A.The Fool #include <bits/stdc++.h> using namespace std; inline int read() { ,f=;char ch=getch ...

  4. Luogu P1462 通往奥格瑞玛的道路 二分答案+最短路

    先二分答案,再跑最短路,跑的时候遇到 过路费超过二分的答案的 就不拿他更新最短路 #include<cstdio> #include<iostream> #include< ...

  5. SSRS-lookupSet-DataSet-分组查询

    SSRS-lookupSet-DataSet-分组查询 来源:http://www.cnblogs.com/biwork/p/3621885.html 目录:http://www.cnblogs.co ...

  6. sqlsever 判断某个字段出现重复的字母或字符

    -------下面使用标量值函数判断  出现重复的个数 create function fn_str_times(@str varchar(1000),--原子符串@indexstr varchar( ...

  7. (译)Cg Programming/Unity(Cg编程/Unity)

    最近在学习Unity3d中的shader编程,能找到的中文资料比较少,于是,尝试翻译一下wiki Books上的资料,以方便其他跟我一样的入门学习者.由于是第一次翻译技术资料,经验不足,难免出错,请路 ...

  8. IOSruntime : 运行时机制

    首先必须明白的: 1.是什么 1> runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API 2> 平时编写的OC代码, 在程序运行过程中, 其实最 ...

  9. HDU 3681 Prison Break 越狱(状压DP,变形)

    题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...

  10. 在Linux系统里安装Virtual Box的详细步骤

    今天我试图在Linux 服务器上安装Kyma时,遇到如下错误消息: E1009 23:51:37.685891 358 start.go:174] Error starting host: Error ...