loj 3158 [NOI2019]序列

loj 3158 [NOI2019]序列

https://loj.ac/problem/3158

UP5sE9.png

UP5641.png

Tutorial

https://www.luogu.com.cn/blog/s-r-f/solution-p5470

考虑建立费用流模型

建立(n)个点表示(a_i),(n)个点表示(b_i),两个中转点(u,v)

源点向每个表示(a_i)的点连((1,a_i)),每个表示(b_i)的点向汇点连((1,b_i)),表示(a_i)的点和表示(b_i)的对应的点之间连((infty,0))

(u)(v)((K-L,0))表示可以不相同的下标对数.每个表示(a_i)的点向(u)((infty,0)),(v)向每个表示(b_i)的连((infty,0)).注意优先流对应的点之间的边.

我们要求的就是流量为(K)时的最大费用.

用模拟费用流解决,注意维护(u,v)之间的边剩余的流量,并尽量使其最大

  1. (u,v)之间未满流,则分别选择(a,b)中最大的点

  2. 否则,有(3)种选择.

  1. 选择一对没有选择过的(a,b)
  2. 选择一个(a)已经被选过的(b),和一个未选择的(a)
  3. 选择一个(b)已经被选过的(a),和一个未选择的(b)

注意2,3可能会产生新的(u,v)间流量

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define fi first
#define se second
using namespace std;
inline char gc() {
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void rd(T &x) {
	x=0; int f=1,ch=gc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=gc();}
	x*=f;
}
typedef long long ll;
const int inf=1e9;
const int maxn=2e5+50;
int T,n,K,L,a[maxn],b[maxn];
int s[maxn];
int main() {
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	rd(T);
	for(int kase=1;kase<=T;++kase) {
		rd(n),rd(K),rd(L);
		for(int i=1;i<=n;++i) rd(a[i]);
		for(int i=1;i<=n;++i) rd(b[i]);
		priority_queue< pair<int,int> > qa,qA,qb,qB,qab;
		{
			pair<int,int> t(-inf,0);
			qa.push(t),qA.push(t),qb.push(t),qB.push(t),qab.push(t);
		}
		memset(s,0,sizeof(s));
		for(int i=1;i<=n;++i) {
			qa.push(make_pair(a[i],i));
			qb.push(make_pair(b[i],i));
			qab.push(make_pair(a[i]+b[i],i));
		}
		ll an=0;
		for(int i=1,flow=K-L;i<=K;++i) {
			while(s[qa.top().se]&1) qa.pop();
			while(s[qA.top().se]&1) qA.pop();
			while(s[qb.top().se]&2) qb.pop();
			while(s[qB.top().se]&2) qB.pop();
			while(s[qab.top().se]) qab.pop();
			if(flow) {
				int p=qa.top().se,q=qb.top().se;
				an+=a[p]+b[q]; 
				s[p]|=1,qB.push(make_pair(b[p],p));
				s[q]|=2,qA.push(make_pair(a[q],q));
				if(p!=q) {
					--flow;
					if(s[q]==3) ++flow;
					if(s[p]==3) ++flow;
				}
				continue;
			}
			int v0=qA.top().fi+qb.top().fi; bool c0=s[qb.top().se];
			int v1=qa.top().fi+qB.top().fi; bool c1=s[qa.top().se];
			int v2=qab.top().fi;
			if(make_pair(v0,c0)>=make_pair(v1,c1)&&v0>=v2) {
				int p=qA.top().se,q=qb.top().se;
				an+=v0,flow+=c0;
				s[p]|=1;
				s[q]|=2,qA.push(make_pair(a[q],q));
			}
			else if(v1>=v2) {
				int p=qa.top().se,q=qB.top().se;
				an+=v1,flow+=c1;
				s[p]|=1,qB.push(make_pair(b[p],p));
				s[q]|=2;
			}
			else {
				int p=qab.top().se;
				an+=v2;
				s[p]=3;
			}
		}
		printf("%lld
",an);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/ljzalc1022/p/13256078.html