vijos1760题解
题目:
现在有n个人,题目给出了他们每个人所在市县的编号。他们站在一个从左向右的队伍中。小L不在队列中。他想找到一个长度不超过D的区域,使他能够找到最多的不同地方的朋友。要求输出能找到的朋友所在不同市县的最大数和找到这些朋友的最小区间长度。比如在整个队伍内他按从左向右顺序找到了3个A地朋友,1个B地朋友,1个C地朋友。假设D=5,那么不同市县的最大数为3(A地、B地、C地),最小区间长度为3(只须结交A地的最右面的一个人即可得到最大市县数3,因此区间长度不是5而是3)。假设在队伍内的人他都还没有结交。
在这里写题解时,我总算是长吐了一口气。(因为vijos1000-1653的大部分数据我都有,而此题我没有数据,要是做错了话,是很难修改的)那么,我就把我一步步的想法写下来。
望到100万的数据,肯定是O(n)或是O(log(n)*n)。
后来还有一个最少人数的要求,很明显用最多人数的算法并二分答案。
然而我并不是天才,一开始是怎么也想不到最多人数算法,只是直接想到暴力枚举。(举报:HHD大神在我开始编之前就AK了!!!!)
首先,我想到链表,而且不能用静态数组去代替。范围是n(100万)*k(32768),但实际上数据也就100万个。我本打算一个数组代表一个省份,里面记录该省份的人出现位置,根据同一数组里前后两个数位置进行操作(事实证明仍有点bug)。可是指针我真心不会,看了半天教程,还是云里雾里的。
接着,我想到了之前想法的实际版(链表的不现实,因为我不会)。我们可以把人和位置快排(双关键字),再在每个省份内的人(此时已经连成一块了)里进行操作,同时加一点类似前缀和的优化。以下代码1即是这种实现。
但是,我发现我样例也过不了,为什么呢?我猛然也发现了BUG。突然,我灵光一现,想到了一种真正的算法。由于打字麻烦,在这里引用HHD大神的题解(果然是英雄所见略同!):
先介绍下问题1的解法:
开一个4W的数组,刚开始置为0,表示该地区的大牛当前有几个,然后O(n)模拟。
先处理下1..d有几个不同的地区,然后每次把第一个去掉,然后后一个加上,即改成:2..d+1,然后3..d+2,最后n-d+1...n
每次去掉时,如果去掉后该地区的大牛没了,当前不同地区数就-1,每次加上时,如果加上后该地区大牛只有一个,那么不同地区数+1,每一轮加入删除后更新下答案,这样问题1O(N)搞定
long getans(long d)
{
if(d==0)return 0; long max=0;long now=0;for(longi=1;i<=39999;i++)temp[i]=0; for(long i=1;i<=d;i++) {temp[dl[i]]++;if(temp[dl[i]]==1)max++; }now=max; for(longi=d+1;i<=n;i++) { temp[dl[i-d]]--;if(temp[dl[i-d]]==0)now--;temp[dl[i]]++;if(temp[dl[i]]==1)now++; if(now>max)max=now;
}return max; }
问题2:我们可以发现,如果D越大,那么覆盖的不同地区肯定是严格递增的,而且D<1000000,所以可以二分,然后用上面的getans(d)来检验。时间效率O(nlogn)
但是,当我编好之后交上去,发现WA了两个点!(在代码二中标注)
仔细检查错误,我先把erfen(1,max)改成erfen(0,max),仍无济于事。
后来,我几乎绝望地初始化改成更大的(之前循环到n),没想到A了!
这说明,数据出的很不严谨,明明只有N个人,编号却有N+!
但我也要注意,以后做题时宁可更严谨些。
以下是代码:
代码一:
#include<stdio.h>
using namespace std;
long a[1000001],t,last,ans,ans2,i,max,n;
bool check(long k)
{
long i;
for (i=1;i<=n-k+1;i++)
if (a[i+k-1]-a[i-1]==ans) returntrue;
return false;
}
long erfen(long l,long r)
{
long mid;
mid=(l+r)/2;
if (check(mid)) return erfen(l,mid);
else return erfen(mid+1,r);
}
int main()
{
scanf("%ld %ld",&n,&max);
last=-1;
for (i=1;i<=n;i++)
{
scanf("%ld",&t);
if (t!=last)a[i]=a[i-1]+1;
else a[i]=a[i-1];
last=t;
}
for (i=1;i<=n-max+1;i++)
if (a[i+max-1]-a[i-1]>ans)ans=a[i+max-1]-a[i-1];
printf("%ld ",ans);
ans2=erfen(1,max);
printf("%ld",ans2);
return 0;
}
代码二:
#include<stdio.h>
using namespace std;
longa[1000001],s[32769],t,last,ans,ans2,i,max,n,cnt;
bool check(long k)
{
long i;cnt=0;
for (i=1;i<=32768;i++)s[i]=0;//以前是i<=n
for (i=1;i<=k;i++)
{
s[a[i]]++;if (s[a[i]]==1)cnt++;
}
if (cnt==ans) return true;
for (i=k+1;i<=n;i++)
{
s[a[i]]++;if (s[a[i]]==1)cnt++;
s[a[i-k]]--;if (s[a[i-k]]==0)cnt--;
if (cnt==ans) returntrue;
}
return false;
}
long erfen(long l,long r)
{
long mid;
if (l==r) return l;
mid=(l+r)/2;
if (check(mid)) return erfen(l,mid);
else return erfen(mid+1,r);
}
int main()
{
scanf("%ld %ld",&n,&max);
cnt=0;
for (i=1;i<=n;i++)
{
scanf("%ld",&a[i]);
}
for (i=1;i<=32768;i++)s[i]=0;//以前是i<=n
for (i=1;i<=max;i++)
{
s[a[i]]++;if (s[a[i]]==1)cnt++;
}
if (cnt>ans) ans=cnt;
for (i=max+1;i<=n;i++)
{
s[a[i]]++;if (s[a[i]]==1)cnt++;
s[a[i-max]]--;if (s[a[i-max]]==0)cnt--;
if (cnt>ans)ans=cnt;
}
printf("%ld ",ans);
ans2=erfen(0,max);//以前是(1,max)
printf("%ld",ans2);
//scanf("%ld",&ans);
return 0;
}
vijos1760题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- 将C-风格字符串用作string对象引用参数
string类定义了一种char*到string的转换功能,这使得可以使用C-风格字符串来初始化string对象. 类型为const引用的形参其中一个属性表明:假设实参的参数类型与引用参数不匹配,但可 ...
- mysql5.6 主从复制
Master 192.168.59.128 Slave 192.168.59.129 默认认为已安装mysql5.6 mysql5.6 rpm安装配置 修改Master my.cnf文件 # ...
- javascript获取json对象的key名称的两种方法
javascript获取json对象的key名称的两种方法 数据处理中,你可能接收到一个不确定内容格式的json对象,然后要把key的值提取出来.今天试过两种可以提取json key的方法,均可以正常 ...
- Vue.js高仿饿了么WebApp
介绍 学习Vue.js也有一阵子了,为了加深对Vue的理解及运用,做了一个小项目.这是一个高仿饿了么外卖WebApp,现已完成商品预览.商品详情.商家预览.添加购物.查看评论等功能. 部分截图 项目预 ...
- HTML输入框只能输入数字或数字字母组合
JS判断只能是数字和小数点 1.文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace(/\D/g,'' ...
- Android控件的使用
1. RadioButton (单选按钮) 嵌入到RadioGroup中实现单选效果 android:checkedButton="radio的id值" int getchecke ...
- 你是否也在学习ES6 Promise时遇到过这个问题?
背景 周末闲来无事,随便翻看了一下阮一峰老师的<ES6 标准入门>第2版,ps:之前在阮一峰老师的官网看过电子版,感觉干货满满,所以就买了纸质版:当看到第16章第4节 'Promise.p ...
- 初始化CSS
为什么要初始化CSS? 建站老手都知道,这是为了考虑到浏览器的兼容问题,其实不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面差异.当然,初始化样式会对SEO有一定的 ...
- SQL Server 实现Split函数
添加一个表值函数. CREATE function [dbo].[fnSplit] ( ), --要分割的字符串 ) --字符串之间的分隔符 ) ,), TempName )) as begin de ...
- Scrapy爬虫大战京东商城
Scrapy爬虫大战京东商城 引言 上一篇已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇 代码详解 首先应该构造请求,这里使用scrapy.Request,这个方法默认调 ...