题目:

现在有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题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. 开涛spring3(6.5) - AOP 之 6.5 AspectJ切入点语法详解

    6.5.1  Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的Aspect ...

  2. Ionic进行PC端Web开发时通过脚本压缩提高第一次加载效率

    1. 问题 1.1. 问题上下文描述: 基于Ionic进行PC端的Web应用开发: 使用Tomcat作为最终服务发布容器. 1.2. 问题描述: 编译后main.js的大小为4-6MByte.(集成第 ...

  3. npm 一条命令更换淘宝源

    一条命令更换淘宝源 npm config set registry https://registry.npm.taobao.org

  4. java设计模式面试考点

    分类(常见的设计模式) 1.创建型模式 a) 工厂模式 b) 抽象工厂模式 c) 单例模式 d) 建造者模式 2.结构型模式 a) 适配器模式 b) 装饰器模式 c) 桥接模式 d) 代理模式 3.行 ...

  5. Spring MVC 学习笔记一 HelloWorld

    Spring MVC 学习笔记一 HelloWorld Spring MVC 的使用可以按照以下步骤进行(使用Eclipse): 加入JAR包 在web.xml中配置DispatcherServlet ...

  6. Android高效内存1:一张图片占用多少内存

    在做内存优化的时候,我们发现除了解决内存泄露问题,剩下的就只有想办法减少真实的内存占用.而在App中,大部分内存可能被我们图片占用了,所以减少图片的内存占用可以带来直接的效果.本文就简单介绍一张图片到 ...

  7. Hadoop的编译

    Hadoop2.4.0  重新编译 64  位本地库 原创作者:大鹏鸟 时间:2014-07-28 环境:虚拟机 VirtualBox,操作系统 64 位 CentOS 6.4 下载重新编译需要的软件 ...

  8. 剖析WPF数据绑定机制

    引言 WPF框架采取的是MVVM模式,也就是数据驱动UI,UI控件(Controls)被严格地限制在表示层内,不会参与业务逻辑的处理,只是通过数据绑定(Data Binding)简单忠实地表达与之绑定 ...

  9. JDK并发包

    JDK5之后引进了并发包java.util.concurrent,让并发的开发更加可控,更加简单.所以有必要好好学习下,下面从同步控制.并发容器.线程池三部分来详细了解它. 1. 各种同步控制工具的使 ...

  10. 开始学习机器学习,从Ng的视频开始

    时隔开5个月,忙完了考研和毕设后终于有时间搞自己想搞得,研究生导师方向是图像处理与机器学习结合,重新开工 何为机器学习? 对于机器学习(Machine Learning)的定义大体上有两种,第一种是美 ...