[NOI2019] 序列(模拟费用流)

原先自己想的建图:
在这里插入图片描述
正确建图:
在这里插入图片描述
但是 n 太大了,所以考虑模拟费用流:
在这里插入图片描述
注意:
在1中,
若选的两个位置相同,则为情况2,不用减 f;
若选的位置在另一序列中已被选,则为情况3或4,不用减 f;
若选的位置在另一序列中都已被选,则为情况5,把 f 加1。

在3,4中,
若选的位置在另一序列中都已被选,则为情况5,把 f 加1。

更多细节详见代码:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int N=200010;
struct que{
    
    
	int val,id;
	que(){
    
    }
	que(int v,int i){
    
    
		val=v;id=i;
	}
};
bool operator < (const  que a, const que b){
    
    
	return a.val<b.val;
}
priority_queue<que> pa,pb,pc,pd,psum,nul;
int T,n,K,L,A[N],B[N],flagA[N],flagB[N];
int main(){
    
    
	scanf("%d",&T);
	while(T--){
    
    
		pa=pb=pc=pd=psum=nul;//初始化 
		scanf("%d%d%d",&n,&K,&L);
		for(int i=1;i<=n;i++) scanf("%d",&A[i]);
		for(int i=1;i<=n;i++) scanf("%d",&B[i]);
		for(int i=1;i<=n;i++){
    
    
			pa.push(que(A[i],i));
			pb.push(que(B[i],i));
			psum.push(que(A[i]+B[i],i));
			flagA[i]=flagB[i]=0;
		}
		int f=K-L;
		ll ans=0;
		for(int i=1;i<=K;i++){
    
    
			que ra,rb,rc,rd,rsum;
			while(!pa.empty()){
    
    
				ra=pa.top();
				if(!flagA[ra.id]) break;
				pa.pop();
			} 
			while(!pb.empty()){
    
    
				rb=pb.top();
				if(!flagB[rb.id]) break;
				pb.pop();
			}
			if(f>0){
    
    
				if(flagB[ra.id]) f+=1;
				if(flagA[rb.id]) f+=1;
				if(ra.id==rb.id) f+=1;
				flagA[ra.id]=flagB[rb.id]=1;
				pa.pop();
				pb.pop(); 
				pc.push(que(A[rb.id],rb.id));
                pd.push(que(B[ra.id],ra.id));
                f-=1;
                ans+=ra.val+rb.val;
                continue;
			}
			while(!pc.empty()){
    
    
				rc=pc.top();
				if(!flagA[rc.id]) break;
				pc.pop();
			} 
			while(!pd.empty()){
    
    
				rd=pd.top();
				if(!flagB[rd.id]) break;
				pd.pop();
			}
			while(!psum.empty()){
    
    
				rsum=psum.top();
				if(!flagA[rsum.id]&&!flagB[rsum.id]) break;
				psum.pop();
			} 
			int maxn=-1;
			int x=-1;
			if(!psum.empty()&&rsum.val>maxn) maxn=rsum.val,x=2;
			if(!pc.empty()&&!pb.empty()&&rc.val+rb.val>maxn) maxn=rc.val+rb.val,x=3;
            if(!pd.empty()&&!pa.empty()&&rd.val+ra.val>maxn) maxn=rd.val+ra.val,x=4;
            ans+=maxn;
            if(x==2){
    
    
            	flagA[rsum.id]=flagB[rsum.id]=1;
            	psum.pop();
			}
			else if(x==3){
    
    
				if(flagA[rb.id]) f+=1;
                flagA[rc.id]=flagB[rb.id]=1;
                pc.pop();
                pb.pop();
                pc.push(que(A[rb.id],rb.id));
			}
			else if(x==4){
    
    
				if(flagB[ra.id]) f+=1;
                flagA[ra.id]=flagB[rd.id]=1;
                pa.pop();
                pd.pop();
                pd.push(que(B[ra.id],ra.id));
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Emma2oo6/article/details/106722208