题目:

现在有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. redis入门指南-附录B

  2. php微信支付问题之 cURL error 60: SSL certificate: unable to get local issuer certificate

    cacert.pem(点击下载) 解决办法:比如我本地安装的是wamp,将cacert.pem文件放在这个文件夹下面D:\wamp\bin\php\php5.5.12\ext 如果安装的phpStud ...

  3. What does a Bayes factor feel like?(转)

    A Bayes factor (BF) is a statistical index that quantifies the evidence for a hypothesis, compared t ...

  4. Comparing the contribution of NBA draft picks(转)

    When it comes to the NBA draft, experts tend to argue about a number of things: at which position wi ...

  5. OOP中this指向详解

    谁调用了函数,this就指向谁 >>> this指向的永远只可能是对象!!! >>> this指向谁,永远不取决于this写在哪,而是取决于函数在哪调用!!! &g ...

  6. Android WebView 不支持 H5 input type="file" 解决方法

    最近因为赶项目进度,因此将本来要用原生控件实现的界面,自己做了H5并嵌入webview中.发现点击H5中 标签 不能打开android资源管理器. 通过网络搜索发现是因为 android webvie ...

  7. 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率

    隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法 ...

  8. 排序算法 - 选择排序(selection sort)

    选择排序(Selection sort)跟插入排序一样,也是O(n^2)的复杂度,这个排序方式也可以用我们的扑克牌来解释. 概念 桌面上有一堆牌,也是杂乱无章的,现在我们想将牌由小到大排序,如果使用选 ...

  9. CoreAnimation学习,学习总结,记录各种过程中遇到的坑

    1. CAAimation  的 duration = 0 的时候, 这个时候就相当于没有动画了. 2. CAKeyframeAnimation *rotateAnimation = [CAKeyfr ...

  10. MVC 树节点Table格式授权

    这几夜心里颇不平静, 奈何 JS水平有限,前台效果耗时四天,后台传值一天,直至昨夜丑时测试初步完成,其实就是一个给tree来授权,网上开源的插件很多,如treejs.easyui 等等,只是这里授权稍 ...