题目:

现在有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. MYBATIS 简单整理与回顾

    这两天简单整理了一下MyBatis 相关api和jar包这里提供一个下载地址,免得找了 链接:http://pan.baidu.com/s/1jIl1KaE 密码:d2yl A.简单搭建跑项目 2.进 ...

  2. Lua学习(4)——函数

    在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y).唯一的差别是,如果函数只有一个参数,并且该参数的类型为字符串常量 ...

  3. python之路 序列化 pickle,json

    运行代码,毫不留情地得到一个TypeError: Traceback (most recent call last): ... TypeError: <__main__.Student obje ...

  4. SQL注入攻击[详解]

    SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候, ...

  5. socket聊天室(服务端)(多线程)(TCP)

    #include<string.h> #include<signal.h> #include<stdio.h> #include<sys/socket.h&g ...

  6. Spring MVC 学习笔记一 HelloWorld

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

  7. docker dead but pid file exists 问题

    You may have to enable the public_ol6_latest repo in order to get this package. sudo yum-config-mana ...

  8. dedecms做好的网站怎么上传到网上?

    1.首先做好网站后把网站所有和数据库备份 dedecms  点击 系统 - 数据库备份/还原 - 全选  后---提交-----等待备份完全 备份文件在哪里:data/backupadta--- 2. ...

  9. 数据结构与算法1-2 C语言运行时间检测算法

    #include <stdio.h> #include <math.h> #include <time.h> clock_t start,stop; #define ...

  10. MySQL基础语法------增删改查

    1.增 1.1建立数据库 create database test2; 格式:create database <数据库名> 1.2建表 create table student( sno ...