P5470 [NOI2019]序列

链接:https://www.luogu.com.cn/problem/P5470

题目描述:给定两个序列a,b,在两个序列中分别取出两个大小为K下标集A,B使得A,B交的个数>=L,最大化取出下标的对应元素权值和。

题解:首先可以建出费用流模型:

令序列A元素为i,序列B元素为i

然后连(s,i),流量为1,费用为ai

(i,t),流量为1,费用为bi

(i,i),流量为1,费用为0

由于有L的限制,那么随便连就有KL的限制:

那么可以连(i,U),流量为1,费用为0

那么可以连(U,V),流量为KL,费用为0

那么可以连(V,i),流量为1,费用为0

当然对于源点要限制只有大小为K的流,那么连(s,s),流量为K,费用为0,将s置为源点。

现在考虑有以下几种流:

1.s>i>i>t,即选两个下标相当的元素。

2.s>i>U>V>j>t,即选两个下标不相当的元素,此时(U,V)花费1流量。

3.s>i>i>V>j>t,此时i>V时被翻转的,从前i就被流过,那么就是选了i,j,即选了i被使用过的一个i与一个j,不花费(U,V)流量。

4,不难发现有一种与3对称的流,选了i被使用过的一个i与一个j,不花费(U,V)流量。

5.s>i>i>V>U>j>j>t,此时(i,V),(V,U),(U,j)均被翻转过。那么,即选了i被使用过的一个i与一个j被使用的j,反加(U,V)流量。而它的对称流还是5

所以我们可以拿5个堆模拟上述过程,令qa表示没用过ii集合,qb表示没用过jj集合,ta表示用过ii集合,tb表示用过jj集合,p表示i,i都没用过组成的集合。

1p

2qa+qb

3ta+qb

4qa+tb

5ta+tb

然后模拟费用流即可,注意p包含了qa,qb,所以可能会有1被误判为2的情况,将1置在2前即可。

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct reads
{
  long long num,data;
  bool operator < (const reads &a)const
  {
    return data<a.data;
  }
};
priority_queue<reads>qa;
priority_queue<reads>qb;
priority_queue<reads>ta;
priority_queue<reads>tb;
priority_queue<reads>p;
long long T,n,k,L,s,maxn,maxer,ans,A[1000001],B[1000001];
bool t,usedA[1000001],usedB[1000001];
int read()
{
  char c=0;
  int sum=0;
  while (c<'0'||c>'9')
    c=getchar();
  while ('0'<=c&&c<='9')
    {
      sum=sum*10+c-'0';
      c=getchar();
    }
  return sum;
}
reads tmp;
reads make_reads(int x,int y)
{
  tmp.num=x;
  tmp.data=y;
  return tmp;
}
int main()
{
  T=read();
  while (T--)
    {
      n=read(),k=read(),L=read();
      while (!qa.empty())
	qa.pop();
      while (!qb.empty())
	qb.pop();
      while (!p.empty())
	p.pop();
      while (!ta.empty())
	ta.pop();
      while (!tb.empty())
	tb.pop();
      for (int i=1;i<=n;++i)
	{
	  usedA[i]=0;
	  A[i]=read();
	  qa.push(make_reads(i,A[i]));
	}
      for (int i=1;i<=n;++i)
	{
	  usedB[i]=0;
	  B[i]=read();
	  qb.push(make_reads(i,B[i]));
	}
      for (int i=1;i<=n;++i)
	p.push(make_reads(i,A[i]+B[i]));
      s=k-L;
      ans=0;
      while (k--)
	{
	  maxn=0;
	  while (!qa.empty()&&usedB[qa.top().num])
	    qa.pop();
	  while (!qb.empty()&&usedA[qb.top().num])
	    qb.pop();
	  while (!p.empty()&&(usedA[p.top().num]||usedB[p.top().num]))
	    p.pop();
	  if (!p.empty()&&p.top().data>maxn)
            {
	      maxn=p.top().data;
              maxer=5;
            }
	  if (s)
	    {
	      if (!qa.empty()&&!qb.empty()&&qa.top().data+qb.top().data>maxn)
		{
		  maxn=qa.top().data+qb.top().data;
		  maxer=1;
		}
	    }
	  if (!qa.empty()&&!tb.empty()&&qa.top().data+tb.top().data>maxn)
	    {
	      maxn=qa.top().data+tb.top().data;
	      maxer=2;
	    }
	  if (!ta.empty()&&!qb.empty()&&ta.top().data+qb.top().data>maxn)
	    {
	      maxn=ta.top().data+qb.top().data;
	      maxer=3;
	    }
	  if (!ta.empty()&&!tb.empty()&&ta.top().data+tb.top().data>maxn)
	    {
	      maxn=ta.top().data+tb.top().data;
	      maxer=4;
	    }
	  ans+=maxn;
	  if (maxer==1)
	    {
	      s--;
	      tb.push(make_reads(qa.top().num,B[qa.top().num]));
	      ta.push(make_reads(qb.top().num,A[qb.top().num]));
	      usedA[qa.top().num]=1;
	      usedB[qb.top().num]=1;
	      qa.pop();
	      qb.pop();
	    }
	  if (maxer==2)
	    {
	      usedA[qa.top().num]=1;
	      usedB[tb.top().num]=1;
	      tb.pop();
	      tb.push(make_reads(qa.top().num,B[qa.top().num]));
	      qa.pop();
	    }
	  if (maxer==3)
	    {
	      usedA[ta.top().num]=1;
              usedB[qb.top().num]=1;
              ta.pop();
              ta.push(make_reads(qb.top().num,A[qb.top().num]));
	      qb.pop();
	    }
	  if (maxer==4)
	    {
	      s++;
	      usedA[ta.top().num]=1;
	      usedB[tb.top().num]=1;
	      ta.pop();
	      tb.pop();
	    }
	  if (maxer==5)
	    {
	      usedA[p.top().num]=1;
	      usedB[p.top().num]=1;
	    }
	}
      printf("%lld\n",ans);
    }
  return 0;
}
posted @   zhouhuanyi  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示
主题色彩