codevs 1394 数字串 贪心 解题报告
来源:互联网 发布:非常嫌疑犯影评知乎 编辑:程序博客网 时间:2024/06/05 00:47
题目描述 Description
给你一个长度为n的数字串,数字串里会包含1-m这些数字。如果连续的一段数字子串包含了1-m这些数字,则称这个数字字串为NUM串。你的任务是求出长度最短的NUM串是什么,只需要输出这个长度即可。
1<=n,m<=200000
输入描述 Input Description
第一行给定n和m。
第二行n个数,表示数字串,数字间用空格隔开。
输出描述 Output Description
如果存在NUM串则输出最短NUM串长度,否则输出“NO”。
样例输入 Sample Input
5 3
1 2 2 3 1
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
各个测试点1s
思路
最简单的想法是,暴力枚举左右端点形成序列,在序列中分别查找每个不大于m的正整数。时间复杂度O(n^3·m)。
可以想到的一个简单优化是,可以枚举左端点,然后不断向右扫描,用一个桶d[]来统计每个不大于m的正整数出现的次数。
则当d[]中的每个元素都大于0时,即每个不大于m的正整数都有出现时,结束当次扫描,修改最小值,选择下一个左端点。时间复杂度O(n^2·m)。
可以想到,每次只修改某单个d[i],即令d[i]增加1,却要把整个数组扫描一次来判断,是很浪费时间的。我们可以令cnt为d[]中值大于0的元素个数,且初始化为0。
每次令d[i]增加1后,若d[i]的变化是从0到1,则令cnt增加1。当cnt=m时就知道当前数段已经满足要求了,不必次次把d[]扫描一次。时间复杂度O(n^2+nm)。
但是本题要求一个线性的做法,每次选择好左端点然后从原地开始向右扫描,显然是二次方的。是否一定要从原地开始扫描呢?
令f[i]为当左端点为i时,最小的使得数段[i,j]满足要求的j。如n=5,m=3且序列为1,3,3,2,1,当左端点为1时向右扫描,直到扫描到第4个数,才能使得当前数段1,3,3,2满足要求。
而以2为左端点则要扫描到第5个数才可以。因此定义f[1]=4,f[2]=5,同理f[3]=5,而f[4]和f[5]为无穷大。则只需要在所有f[i]-i+1中找一个最小值即可。
应该注意到,f[i]关于i是单调的,当i增加时,f[i]不会减少。如果有i
代码
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<cmath>using namespace std;const int N=200000+5;const int inf=0x3f3f3f3f;int work[N],pos=0,num[N],n,m,j=1,ans,t,now;int main(){ ans=inf; memset(work,0,sizeof(work)); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&num[i]); now=0; while((pos<m)&&(now<=n)) { now++;work[num[now]]++; if (work[num[now]]==1) pos++; } if (now>n) { printf("NO"); return 0; } ans=now; while(now<=n) { work[num[now]]++; if (work[num[now]]==1) pos++; while((pos>m)||(pos=m)&&(work[num[j]]>1)) { work[num[j]]--; if (work[num[j]]==0) pos--; j++; } if (now-j+1<ans) ans=now-j+1; now++; } printf("%d\n",ans); return 0;}
- codevs 1394 数字串 贪心 解题报告
- codevs 1214 线段覆盖 贪心 解题报告
- vijos P1005 超长数字串 解题报告
- Codevs 1008 选数 解题报告
- codevs 1009 产生数 Floyd 解题报告
- codevs 1052 地鼠游戏 堆优化贪心 解题报告
- codevs 1144 守望者的逃离 贪心? 解题报告
- ZZULI 1234 数字串 解题报告
- codevs 2147 数星星 离散化?解题报告
- 【贪心】数字串
- [CODEVS]数据结构系列 解题报告
- CODEVS 1022 覆盖 解题报告
- [codevs 1515]跳 【解题报告】
- Codevs 1251 括号 解题报告
- Codevs 1557 热浪 解题报告
- CodeVS 2370 LCA 解题报告
- codevs 1006 等差数列 解题报告
- POJ1328解题报告 (贪心)
- codevs 1557 热浪 SPFA 解题报告
- 初学python 解压手写训练图片
- hdu 3555(数位dp)
- Android Fragment onAttach() deprecated
- Mybatis初窥:动态SQL
- codevs 1394 数字串 贪心 解题报告
- telnet发邮件
- K:Eclipse Memory Analyzer的安装和使用
- [Django]Django官方文档的投票Web应用笔记
- 单层感知器的局限性--异或问题
- 设计模式
- 数据结构——顺序表逆置之移位算法
- eclipse 连接到 Hive 时的异常
- JavaScript读书学习笔记(三)——BOM