zoukankan      html  css  js  c++  java
  • 环中环 (Standard IO)

    Description

      被认为天才的小头遇到麻烦了!!这天数学课老师给出了一道难题,而小头居然没能在3秒内解决,可见此题难度之大。
      问题是这样的:n个整数围成一个环,老师要求选出其中的若干数,使得选中的数所组成的环中,两个相邻数的差的绝对值不等于1。在满足这个前提下,问最多能取多少个数。

    Input

      第一行一个正整数n,表示有n个数
      第二行n个整数,a1、a2……an 按顺时针方向围成一个环。

    Output

      一个正整数,即表示最多能选多少个数。
     
    题解
    需要发现一个性质。即枚举完起点把环转化成一行后,用dp[i]表示以第i个数结尾最多能选多少个数,那么在求dp[i]时只需要记录dp[1]到dp[i-1]里前3大的数就可以了(显然3个不同数中至少有一个和a[i]的绝对值不等于1)。同理,在枚举起点时也只要枚举前5个不同的数。因此该题复杂度为O(N)。
    但本人笨,不会。于是在用LXF的方法做对。
    用dp[i]表示以第i个数结尾最多能选多少个数。
    那我们只能在dp[1]..d[i-1]的范围中找到一个最大的dp[j],且a[j]是在 0..a[i]-2,a[i],a[i]+2..max的范围中(因为a[i]-1和a[i]+1与a[i]的差的绝对值等于1)。
    可以把原队列复制一次在队尾,把数的个数变成n*2,就可以处理环的最后一个数和第一个数是否冲突。
    输出时输出max(dp[i]) div 2。
    可以用线段树来优化这一过程(范围找最大)。

    最后,我在此吐槽一句,后面的方法是水解。因为数据太水。我的代码不能处理(3,3,3,3,6,6,6,2,2,4,4)结果是7,而我的是9。希望大家能告诉我那错了。

    代码

    type
      arr=record
            nm,w:longint;
          end;
    var
      ans,n,m:longint;
      t:array [0..400001] of longint;
      f,h:array [0..200001] of longint;
      a:array [0..200001] of arr;
    function max(o,p:longint):longint;
    begin
      if o>p then exit(o)
             else exit(p);
    end;
    
    function ins(p,x,y,l,r:longint):longint;
    var
      mid:longint;
    begin
      if (x=l) and (y=r) then exit(t[p]);
      mid:=(l+r) div 2;
      if y<=mid then exit(ins(p*2,x,y,l,mid)) else
        if mid+1<=x then exit(ins(p*2+1,x,y,mid+1,r)) else
          exit(max(ins(p*2,x,mid,l,mid),ins(p*2+1,mid+1,y,mid+1,r)));
    end;
    
    procedure count(x,y,l,r,sum:longint);
    var
      mid:longint;
    begin
      if l=r then
        begin
          t[x]:=max(t[x],sum);
          exit;
        end;
      mid:=(l+r) div 2;
      if y<=mid then count(x*2,y,l,mid,sum)
                else count(x*2+1,y,mid+1,r,sum);
      t[x]:=max(t[x*2],t[x*2+1]);
    end;
    
    procedure qsort(l,r:longint);
    var
      i,j,mid:longint;
    begin
      i:=l; j:=r;
      mid:=a[(l+r) div 2].nm;
      repeat
        while a[i].nm<mid do inc(i);
        while a[j].nm>mid do dec(j);
        if i<=j then
          begin
        a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
        inc(i); dec(j);
          end;
      until i>j;
      if l<j then qsort(l,j);
      if i<r then qsort(i,r);
    end;
    
    procedure main;
    var
      i,x,y,z:longint;
    begin
      fillchar(f,sizeof(f),0);
      for i:=1 to n*2 do
        begin
          if h[i]-2>0 then x:=ins(1,1,h[i]-2,1,m)
                      else x:=0;
          if h[i]+2<m+1 then y:=ins(1,h[i]+2,m,1,m)
                else y:=0;
          z:=ins(1,h[i],h[i],1,m);
          f[i]:=max(max(x,y),z)+1;
          count(1,h[i],1,m,f[i]);
        end;
      ans:=0;
      for i:=1 to n*2 do
        ans:=max(f[i],ans);
    end;
    
    procedure init;
    var
      i:longint;
    begin
      readln(n);
      for i:=1 to n do
        begin
          read(h[i]);
          h[i+n]:=h[i];
        end;
      for i:=1 to n<<1 do
        begin
          a[i].nm:=h[i];
          a[i].w:=i;
        end;
      qsort(1,n*2);
      m:=1;
      h[a[1].w]:=m;
      for i:=2 to n<<1 do
        begin
          if abs(a[i].nm-a[i-1].nm)=1 then inc(m) else
            if a[i].nm<>a[i-1].nm then inc(m,2);
          h[a[i].w]:=m;
        end;
    end;
    
    begin
      init;
      main;
      write(ans div 2);
    end.
    
  • 相关阅读:
    DDD中的聚合和UML中的聚合以及组合的关系
    服务端高并发分布式架构演进之路
    互联网架构的演变,那些神奇的东西怎么来的?
    WPF 之 创建继承自Window 基类的自定义窗口基类
    IIS 之 在IIS7、IIS7.5中应用程序池最优配置方案
    性能测试工具 之 性能计数器
    IIS 之 线程池最大线程数
    WebService 之 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。
    IIS 之 Web 服务器上的 ASP.NET 进程模型设置
    ADO.Net 之 数据库连接池(二)
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319598.html
Copyright © 2011-2022 走看看