[CSP-S模拟测试]:简单的填数(贪心+模拟)
题目描述
对于一个长度为$n$,且下标从$1$开始编号的序列$a$,我们定义它是「合法的」,当且仅当它满足以下条件:
·$a_1=1$
·对于$i\in [1,n),a_i\leqslant a_{i+1}\leqslant a_i+1$且$a_{i+1}$为正整数
·对于任意在$a$中出现过的数$v$,记它的出现次数为$s$,则$2\leqslant s\leqslant 5$
给定一个长度为$n$的序列$a$,其中有一些位置为$0$,你需要在这些位置上任意填数,使得$a$成为一个合法的序列,并且最大化$a_n$的值。
输入格式
第一行一个数$n$,表示序列的长度。
第二行$n$个整数,第$i$个整数表示$a_i$,如果$a_i=0$,则表示这个位置没有填数。
输出格式
如果不存在合法的填数方案,则输出$−1$;否则第一行输出一个整数,表示最大的$a_n$;第二行$n$个正整数,第$i$个数表示完成填数后的序列的第$i$个元素。 如果有多组合法的解,输出任意一组
样例
样例输入1:
7
0 1 0 0 0 3 0
样例输出1:
3
1 1 2 2 3 3 3
样例输入2:
4
0 0 0 3
样例输出2:
-1
数据范围与提示
对于$30\%$的数据,$n\leqslant 1,000$;
对于另外$30\%$的数据,数据保证随机生成;
对于$100\%$的数据,$2\leqslant n\leqslant 2\times {10}^5,0\leqslant a_i\leqslant {10}^5$。
题解
对于每个位置维护两个二元组,分别是$up(x,l)$表示当前位置能填的最大值$x$和连续个数$l$;$down(x,l)$表示当前为只能填数的最小值$x$和连续个数$l$。
求$up$就是尽可能的往上升,求$down$反之。
第一问就是最后一位的最大值,至于第二问倒着扫一边即可求出。
时间复杂度:$\Theta(n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
int n;
int a[200001];
pair<int,int> up[200001],down[200001];
int sum[100001],ans[200001];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
if(a[1]>1){puts("-1");return 0;}
a[1]=1;
up[1]=down[1]=make_pair(1,1);
for(int i=2;i<=n;i++)
{
up[i]=make_pair(up[i-1].first,up[i-1].second+1);
down[i]=make_pair(down[i-1].first,down[i-1].second+1);
if(up[i].second>2)
{
up[i].first++;
up[i].second=1;
}
if(down[i].second>5)
{
down[i].first++;
down[i].second=1;
}
if(a[i])
{
if(up[i].first==a[i])up[i].second=min(up[i].second,2);
if(up[i].first>a[i])up[i]=make_pair(a[i],2);
if(down[i].first<a[i])down[i]=make_pair(a[i],1);
if(up[i].first<a[i]||down[i].first>a[i]){puts("-1");return 0;}
}
}
if(up[n].second==1)up[n]=make_pair(up[n-1].first,up[n-1].second+1);
printf("%d\n",up[n].first);
ans[n]=up[n].first;
sum[a[n]]=1;
for(int i=n-1;i;i--)
{
if(a[i])ans[i]=a[i];
else
{
int flag=min(ans[i+1],up[i].first);
if(sum[flag]==5)flag--;
ans[i]=flag;
}
sum[ans[i]]++;
}
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
return 0;
}
rp++
[CSP-S模拟测试]:简单的填数(贪心+模拟)的更多相关文章
- NOIP模拟测试「简单的区间·简单的玄学·简单的填数·简单的序列」
简单的区间 $update$ 终于$AC$了 找到$(sum[r]+sum[l](sum表示以中间点为基准的sum)-mx)\%k==0$的点 注意这里$sum$表示是以$mid$为基准点,(即$su ...
- noip模拟12[简单的区间·简单的玄学·简单的填数]
noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...
- NOIP 模拟 $12\; \text{简单的填数}$
题解 一个纯的贪心,被我搞成 \(dp\) 了,最后把错解删掉了,骗了 \(10pts\) 考虑如何贪心,设置一种二元组 \((x,l)\),\(x\) 表示当前值,\(l\) 表示当前最长连续长度. ...
- [CSP-S模拟测试]:飞(fly)(数状数组+简单几何)
题目描述 $liu\_runda$决定提高一下知识水平,于是他去请教郭神.郭神随手就给了$liu\_runda$一道神题,$liu\_runda$并不会做,于是把这个题扔到联考里给高二的做.郭神有$n ...
- [CSP-S模拟测试]:简单的括号序列(组合数)
题目传送门(内部题82) 输入格式 一行一个字符串$ss$,保证$ss$中只包含$'('$和$')'$. 输出格式 一行一个整数,表示满足要求的子序列数对$10^9+7$的结果. 样例 样例输入1: ...
- [CSP-S模拟测试]:小L的数(数位DP+模拟)
题目传送门(内部题132) 输入格式 第一行一个整数$t$. 接下来$t$行每行一个整数$n$. 输出格式 $t$行,每行一个整数表示答案. 样例 样例输入: 41818231232691052109 ...
- [CSP-S模拟测试]:简单计算(数学)
题目传送门(内部题104) 输入格式 第一行一个正整数$T$,表示该测试点内的数据组数,你需要对该测试点内的$T$组数据都分别给出正确的答案才能获得该测试点的分数. 接下来$T$组数据,每组数据一行两 ...
- [CSP-S模拟测试]:简单的操作(二分图+图的直径)
题目描述 从前有个包含$n$个点,$m$条边,无自环和重边的无向图. 对于两个没有直接连边的点$u,v$,你可以将它们合并.具体来说,你可以删除$u,v$及所有以它们作为端点的边,然后加入一个新点$x ...
- [CSP-S模拟测试]:简单的期望(DP)
题目描述 从前有个变量$x$,它的初始值已给出. 你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$. 假设最后得到的值为$ ...
随机推荐
- [NOIP2015]子串 题解
题目描述 有两个仅包含小写英文字母的字符串A和B. 现在要从字符串A中取出k个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可 ...
- [CSP-S模拟测试]:marshland(最大费用可行流)
题目描述 前方有一片沼泽地.方便地,我们用一个$n\times n$的网格图来描述它,每一个格子代表着沼泽地的一小片区域.其中$(1,1)$代表网格图的左上角,$(n,n)$代表网格图的右下角.若用$ ...
- mysql经典面试题之学生成绩表
需要数据库表1.学生表 Student(SID,Sname,Sage,Ssex) --SID 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 2.课程表 Course(CID, ...
- obj文件中的关键字
obj文件使用的关键字 关键字 含义 v 表示本行指定一个顶点,此关键字后跟着3个单精度浮点数,分别表示该顶点的X.Y.Z坐标值 vt 表示本行指定一个纹理坐标,此关键字后跟着两个单精度浮点数,分别表 ...
- Vue2.0---vuex初理解
先来一张vuex的帅照 第一眼看到这张图片我内心是万匹草泥马飞过. 简单理解: vuex:一个可以全局被使用的状态管理的“仓库”:state.js中定义初始状态,通过action去触发mutatio ...
- byte与base64string的相互转化以及加密算法
//在C#中 //图片到byte[]再到base64string的转换: Bitmap bmp = new Bitmap(filepath); MemoryStream ms = new Memory ...
- 系统安装2---BIOS设置
对于新的电脑通过U盘安装Windows系统,我们第一步绝对是修改BIOS设置.在这里面我们要修改几项比较重要的选项.如下介绍: 修改第一启动项:目的就是让电脑的第一启动项变为U盘启动. 调节引导方式: ...
- 解决Ubuntu与Windows双系统时间不同步问题
目录 1.Windows修改法 1.1设置UTC 1.2恢复LocalTime 2.Ubuntu修改法 2.1设置LocalTime 2.2恢复UTC 切换系统后,往往发现时间差了8小时.这恰恰是北京 ...
- vscode中git的配置
vscode中对git进行了集成,很多操作只需点击就能操作,无需写一些 git 指令. 不过这就需要你对vscode进行配置.下面我会讲到 git 的配置与免密码上传 github VSCode配置g ...
- 隐藏父类方法的new和重写父类虚方法virtual的区别
一.代码 public class Parent { public void Method_A() { Console.WriteLine("Parent Method_A"); ...