\(CF1615G\)

Description

给定一个数列 \(a\),你需要将所有 \(a_i=0\) 的位置填上一个 \(1\sim n\) 的正整数,使得数列的「值」最大。

数列的值定义为满足以下条件的 \(k\) 的个数:

  • 存在 \(i\in\Z[1,n-1]*i*∈Z[1,*n*−1]\),使得 \(a_{i}=a_{i+1}=k\)。

输出值最大的序列,若有多解,输出任意一个。

\(0\le a\le \min(n,600)\);\(0<n\le 3\times 10^5\)

Solution

转化到匹配问题是比较直觉的?

一开始的错误思路是直接对于每个数匹配位置,会出现这种情况

\(01000020\),直接匹配的话可能会出现,\(01100220\),最优匹配显然是\(11000022\)

那么考虑我们初始状态是一段连续的非\(0\)和\(0\)拼接而成,我们考虑进行连续段匹配

比较显然的几个结论

长度为偶数的 \(0\) 段,两边都匹配或者两边都不匹配,是肯定不劣的

长度为奇数的 \(0\) 段,只有一边匹配或者不匹配,也是不劣的

那么对于这个模型建图:

长度偶数段:左右端点连边,左右边界分别和左右端点连边

长度奇数段:左右边界和区间连边

跑一遍最大匹配就好了,由于是一般图,带花树(复杂度稳定过不去)\(/\)随机匈牙利(直接踩过去)

#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
int match[MAXN],vis[MAXN],a[MAXN],Lim=600,Tim,n;
mt19937 my_rd(time(0));
vector<int>rd[MAXN];
map<int,int>py[605];
bool No[MAXN];
void add(int u,int v)
{
if(No[u]||No[v]) return ;
rd[u].push_back(v);
rd[v].push_back(u);
}
bool dfs(int now)
{
shuffle(rd[now].begin(),rd[now].end(),my_rd);
vis[now]=Tim;
for(int i=0;i<rd[now].size();i++)
{
int y=rd[now][i];
if(vis[match[y]]==Tim) continue;
int z=match[y];
match[now]=y;
match[y]=now;
match[z]=0;
if(!z||dfs(z)) return true;
match[now]=0;
match[y]=z;
match[z]=y;
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
if(a[i]==a[i+1]) No[a[i]]=true;
}
No[0]=true;
for(int i=1,j=0;i<=n;i++)
{
if(a[i])
{
if(j+1==i) goto EB;
else if((i-j)%2==1)
{
Lim++;
add(a[j],Lim); py[a[j]][Lim]=j+1;
add(a[i],Lim+1); py[a[i]][Lim+1]=i-1;
add(Lim,Lim+1);
Lim++;
}
else
{
Lim++;
add(a[j],Lim); py[a[j]][Lim]=j+1;
add(a[i],Lim); py[a[i]][Lim]=i-1;
}
EB:;
j=i;
}
}
for(int T=1;T<=3;T++)
{
for(int i=1;i<=Lim;i++)
{
if(!match[i]) Tim++,dfs(i);
}
}
for(int i=1;i<=600;i++)
{
if(!match[i]||No[i]||!py[i][match[i]]) continue;
a[py[i][match[i]]]=i;
No[i]=true;
}
int num=1;
for(int i=1;i<=n;i++)
{
if(a[i]) continue;
while(No[num]) num++;
if(!a[i]&&!a[i+1])
{
a[i]=a[i+1]=num;
i++;
}
else
{
a[i]=num;
}
num++;
}
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
}

最新文章

  1. 如何在Android中实现全屏,去掉标题栏效果
  2. JS判断日期是否在同一个星期内,和同一个月内
  3. XML序列化的时候如何支持Namespace
  4. duplicate命令创建physical standby数据库报RMAN-03015 ORA-17628
  5. Linux-如何查看登陆shell的类型
  6. WCF中DataContractAttribute 类
  7. mysql时间类型在iBATIS框架下的问题(原创哦)
  8. jquery 创建 SVG DOM 的处理方法
  9. MFC应用程序创建窗口的过程 good
  10. &lt;display:column&gt;属性解释
  11. XMPPclient库Smack 4.0.6一个版本的开发
  12. PuTsangTo-单撸游戏开发02 测试场景与单轴移动
  13. 将搜狗词库(.scel格式)转化为txt格式
  14. 三消游戏FSM状态机设计图
  15. LeetCode(3):无重复字符的最大子串
  16. (原)ubuntu上编译PANet/Detectron.pytorch时-std=c99的错误
  17. coocsCreator杂记
  18. GPT &amp; UEFI Install Windows7
  19. UIScrollView的判断位置的属性如下:
  20. 87. Scramble String *HARD* 动态规划

热门文章

  1. Hadoop安装学习(第二天)
  2. CF1682E Unordered Swaps
  3. 差分优化建边(Tax)
  4. k8s中label和label selector的基本概念及使用方法
  5. 11.Firewalld防火墙
  6. 循序渐进 Redis 分布式锁(以及何时不用它)
  7. Docker-配置华为云加速
  8. Vue 3.0 有哪些新特性值得我们提前了解
  9. React与Koa一起打造一个功能丰富的全栈个人博客(业务篇)
  10. jenkins部署docker