有两种操作是有效的
lowbit(ai)>lowbit(bj) l o w b i t ( a i ) > l o w b i t ( b j ) 或者 ai=bj a i = b j
当 lowbit(ai)>lowbit(bj) l o w b i t ( a i ) > l o w b i t ( b j ) 的 ai a i 和 bj b j 操作时,对答案影响是 lowbit(ai)−lowbit(bj) l o w b i t ( a i ) − l o w b i t ( b j )
当 ai=bj a i = b j 的 ai a i 和 bj b j 操作时,对答案影响是 lowbit(ai) l o w b i t ( a i )
令 cntai c n t a i 表示 A A 中 lowbit(a)=2i l o w b i t ( a ) = 2 i 的个数, cntbi c n t b i 表示 B B , cntc c n t c 表示 a=b a = b 且 lowbit(a)=2i l o w b i t ( a ) = 2 i 的对数
对每个 cntai c n t a i 和 cntbi c n t b i 建一个点
源点向 cntai c n t a i 的点连流量为 cntai c n t a i 费用为 0 的边
cntbi c n t b i 的点向 X X 连流量为 cntbi c n t b i 费用为0的边
X X 向汇点连流量为 k k ,费用为0的边
cntai c n t a i 向 cntbj(j<i) c n t b j ( j < i ) 连流量无穷费用为 2i−2j 2 i − 2 j 的边
cntai c n t a i 向 cntbi c n t b i 连流量为 cntci c n t c i 费用为 2i 2 i 的边
∑lowbit(ai)− ∑ l o w b i t ( a i ) − 最大费用流就是答案
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=1200010,inf=1<<29;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
int n,m,k,a[N],b[N],cnta[40],cntb[40],cntc[40],g[N];
inline int lowest(int x){
int ret=0;
if(x&32767); else ret+=15,x>>=15;
if(x&255); else ret+=8,x>>=8;
if(x&15); else ret+=4,x>>=4;
if(x&3); else ret+=2,x>>=2;
if(x&1); else ret++;
return ret;
}
ll ans,dis[N];
int t,S,T,cnt=1,G[N];
struct edge{
int t,nx,f,c;
}E[N];
inline void addedge(int x,int y,int f,int c){
E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].f=f; E[cnt].c=c; G[x]=cnt;
E[++cnt].t=x; E[cnt].nx=G[y]; E[cnt].f=0; E[cnt].c=-c; G[y]=cnt;
}
queue<int> Q;
int vis[N],frm[N];
inline bool spfa(){
for(int i=S;i<=T;i++) dis[i]=-inf;
vis[S]=1; Q.push(S); dis[S]=0;
while(!Q.empty()){
int x=Q.front(); Q.pop(); vis[x]=0;
for(int i=G[x];i;i=E[i].nx)
if(E[i].f && dis[E[i].t]if(!vis[E[i].t])
vis[E[i].t]=1,Q.push(E[i].t);
}
}
if(dis[T]<=0) return false;
int mf=inf;
for(int i=T;i;i=E[frm[i]^1].t) mf=min(mf,E[frm[i]].f);
ans-=mf*dis[T];
for(int i=T;i;i=E[frm[i]^1].t) E[frm[i]].f-=mf;
return true;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
if(!a[i]) continue;
cnta[lowest(a[i])]++,ans+=a[i]&-a[i];
}
read(m);
for(int i=1;i<=m;i++){
read(b[i]);
if(!b[i]) continue;
cntb[lowest(b[i])]++;
}
sort(a+1,a+1+n); sort(b+1,b+1+m);
for(int i=1,j,p=1;i<=n;i=j+1){
for(j=i;a[j+1]==a[i] && jint cnt=0;
while(p<=m && b[p]while(p<=m && b[p]==a[i]) p++,cnt++;
cnt=min(cnt,j-i+1);
if(!a[i]) continue;
cntc[lowest(a[i])]+=cnt;
}
S=0; t=61; T=62;
for(int i=0;i<30;i++){
for(int j=0;j1,j+31,inf,(1<1<1,i+31,cntc[i],(1<1,cnta[i],0);
addedge(i+31,t,cntb[i],0);
}
read(k);
addedge(t,T,k,0);
while(spfa());
printf("%lld\n",ans);
return 0;
}