LibreOJ545. 「LibreOJ β Round #7」小埋与游乐场【网络流】

545. 「LibreOJ β Round #7」小埋与游乐场

【题目描述】

传送门

【题解】

网络流,我们发现lowbit之后相同的点连出的边是相同的,所以可以缩点。

【代码如下】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=12e6+10,MAXK=505,MAXE=1e4+5,OO=1<<30,LOG=31;
typedef long long LL;
struct Edge{
	int tot,lnk[MAXK],son[MAXE<<1],nxt[MAXE<<1],C[MAXE<<1],W[MAXE<<1];
	void clear(){memset(lnk,-1,sizeof(lnk));tot=-1;}
	void Add(int x,int y,int w,int c){nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;W[tot]=w,C[tot]=c;}
	void Add_E(int x,int y,int w,int c){Add(x,y,w,c);Add(y,x,-w,0);}
}E;
int n,m,K,S,T1,T2,Tim,a[MAXN],Numa[MAXN],b[MAXN],Numb[MAXN],F[LOG],pre[MAXK];LL Ans,Dst[MAXK];bool vis[MAXK];
#include<cctype>
int read(){
	int ret=0;char ch=getchar();bool f=1;
	for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
	for(; isdigit(ch);ch=getchar()) ret=ret*10+ch-48;
	return f?ret:-ret;
}
void Unique(int &L,int *A,int *NumA){
	sort(A+1,A+1+L);int L1=0;
	for(int i=1,j;i<=L;i=j){
		for(j=i+1;j<=L&&A[i]==A[j];j++);
		A[++L1]=A[i];NumA[L1]=j-i;
	}L=L1;
}
int que[MAXK*5],hd,tl;
bool SPFA(int x){
	for(int i=0;i<=T2;i++) Dst[i]=pre[i]=-1,vis[i]=0;
	que[hd=0,tl=1]=x;vis[x]=1;Dst[x]=0;
	while(hd^tl){
		x=que[++hd],vis[x]=0;
		for(int j=E.lnk[x];j^-1;j=E.nxt[j])
		if(Dst[E.son[j]]<Dst[x]+E.W[j]&&E.C[j]>0){
			Dst[E.son[j]]=Dst[x]+E.W[j],pre[E.son[j]]=j;
			if(!vis[E.son[j]]) vis[E.son[j]]=1,que[++tl]=E.son[j];
		}
	}
	if(Dst[T2]==-1) return 0;return 1;
}
LL EK(){
	LL Now=0;
	for(;SPFA(S);){
		int Flow=OO;
		for(int j=pre[T2];j^-1;j=pre[E.son[j^1]]) Flow=min(Flow,E.C[j]);
		for(int j=pre[T2];j^-1;j=pre[E.son[j^1]]) E.C[j]-=Flow,E.C[j^1]+=Flow,Now+=1ll*Flow*E.W[j];
	}
	return Now;
}
int lg2(int x){int j=0;while(x>>1) j++,x>>=1;return j;}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("prob.in","r",stdin);
	freopen("prob.out","w",stdout);
	#endif
	E.clear();
	int nn=read();
	for(int i=1,x;i<=nn;i++){x=read();if(x>0) a[++n]=x,Ans+=a[n]&-a[n];}
	int mm=read();
	for(int i=1,x;i<=mm;i++){x=read();if(x>0) b[++m]=x;}
	sort(a+1,a+1+n);sort(b+1,b+1+m);
	for(int L=1,R,l=1,r;L<=n&&l<=m;L=R){
		for(R=L+1;a[L]==a[R]&&R<=n;R++);
		while(a[L]>b[l]&&l<=m) l++;
		if(a[L]==b[l]){
			for(r=l+1;b[l]==b[r]&&r<=m;r++);
			F[lg2(a[L]&-a[L])]+=min(R-L,r-l);l=r;
		}
	}
	for(int i=1;i<=n;i++) a[i]&=-a[i];
	for(int i=1;i<=m;i++) b[i]&=-b[i];
	Unique(n,a,Numa),Unique(m,b,Numb);S=0,T1=2*LOG+1,T2=T1+1;
	for(int i=1;i<=n;i++)
	E.Add_E(S,lg2(a[i]),0,Numa[i]);
	for(int i=1;i<=m;i++)
	E.Add_E(LOG+lg2(b[i]),T1,0,Numb[i]);
	for(int i=0;i<LOG;i++) if(F[i]) E.Add_E(i,LOG+i,1<<i,F[i]);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m&&b[j]<a[i];j++) E.Add_E(lg2(a[i]),LOG+lg2(b[j]),a[i]-b[j],OO);
	E.Add_E(T1,T2,0,read());
	printf("%lld\n",Ans-EK());
	return 0;
}
posted @ 2019-03-07 20:12  XSamsara  阅读(187)  评论(0编辑  收藏  举报