CLJ神牛的可持久化论文的题目,果然厉害
其实第一步能想到后面就还是很简单的
首先是二分答案,转化为判定性问题
然后对于区间内的数,比他大的标为1,小的标为-1
显然,如果存在一个左右端点符合的区间使得这个区间和大于等于0(因为这里中位数是向下取整)
那么中位数一定是大于等于这个数的,这并不难理解
下面我们就是要快速求出左端点在[a,b],右端点[c,d]的最大区间和
显然可以转化为rmax[a,b]+sum[b+1,c-1]+lmax[c,d];
这里我们不难想到对于每个数建立一个线段树
线段树就是以位置为索引的,记录着区间左最大,区间右最大和区间和
考虑到树的形态都是相同的,我们可以先对数进行排序,然后建立主席树
平时我们的主席树都是在每个位置上建立一棵以键值为索引的线段树,而这里刚好相反
二分答案后就对对应数的线段树求区间最大和

 type node=record
       lm,rm,l,r,s:longint;
     end; var tree:array[..*] of node;
    a,c,h:array[..] of longint;
    q:array[..] of longint;
    j,m,t,ans,n,mid,i,l,r,w:longint; function max(a,b:longint):longint;
  begin
    if a>b then exit(a) else exit(b);
  end; procedure swap(var a,b:longint);
  var c:longint;
  begin
    c:=a;
    a:=b;
    b:=c;
  end; procedure deal;
  var i,j:longint;
  begin
    for i:= to do
      for j:=i+ to do
        if q[i]>q[j] then swap(q[i],q[j]);
  end; procedure sort(l,r: longint);
  var i,j,x,y: longint;
  begin
    i:=l;
    j:=r;
    x:=a[(l+r) shr ];
    repeat
      while a[i]<x do inc(i);
      while x<a[j] do dec(j);
      if not(i>j) then
      begin
        swap(c[i],c[j]);
        swap(a[i],a[j]);
        inc(i);
        j:=j-;
      end;
    until i>j;
    if l<j then sort(l,j);
    if i<r then sort(i,r);
  end;
procedure update(var a,b,c:node);
  begin
    a.s:=b.s+c.s;
    a.lm:=max(b.lm,b.s+c.lm);
    a.rm:=max(c.rm,c.s+b.rm);
  end; function build(l,r:longint):longint;
  var m,q:longint;
  begin
    inc(t);
    if l=r then
    begin
      tree[t].s:=;
      tree[t].lm:=;
      tree[t].rm:=;
      exit(t);
    end
    else begin
      m:=(l+r) shr ;
      q:=t;
      tree[q].l:=build(l,m);
      tree[q].r:=build(m+,r);
      update(tree[q],tree[tree[q].l],tree[tree[q].r]);
      exit(q);
    end;
  end; function work(l,r,last,x:longint):longint;
  var m,q:longint;
  begin
    inc(t);
    if l=r then
    begin
      tree[t].s:=-;
      tree[t].lm:=-;
      tree[t].rm:=-;
      exit(t);
    end
    else begin
      m:=(l+r) shr ;
      q:=t;
      if x<=m then
      begin
        tree[q].r:=tree[last].r;
        tree[q].l:=work(l,m,tree[last].l,x);
      end
      else begin
        tree[q].l:=tree[last].l;
        tree[q].r:=work(m+,r,tree[last].r,x);
      end;
      update(tree[q],tree[tree[q].l],tree[tree[q].r]);
      exit(q);
    end;
  end; function ask(l,r,x,ql,qr:longint):node;  //传递整个node的的写法比我以前的写法要简单不少
  var m:longint;
      s,s1,s2:node;
  begin
    s.lm:=;  s.rm:=;    s.s:=;
    if ql>qr then exit(s);
    if (ql<=l) and (qr>=r) then exit(tree[x])
    else begin
      m:=(l+r) shr ;
      if ql>m then exit(ask(m+,r,tree[x].r,ql,qr));
      if qr<=m then exit(ask(l,m,tree[x].l,ql,qr));
      s1:=ask(l,m,tree[x].l,ql,qr);
      s2:=ask(m+,r,tree[x].r,ql,qr);
      update(s,s1,s2);
      exit(s);
    end;
  end; begin
  readln(n);
  for i:= to n do
  begin
    readln(a[i]);
    c[i]:=i;
  end;
  sort(,n);
  h[]:=build(,n);
  for i:= to n do
    h[i]:=work(,n,h[i-],c[i-]);
  readln(m);
  for i:= to m do
  begin
    for j:= to do
    begin
      read(q[j]);
      q[j]:=(q[j]+ans) mod n+;
    end;
    readln;
    deal;
    l:=;
    r:=n;
    while l<=r do  //二分答案
    begin
      mid:=(l+r) shr ;
      w:=ask(,n,h[mid],q[],q[]).rm+ask(,n,h[mid],q[],q[]).lm+ask(,n,h[mid],q[]+,q[]-).s;
      if w>= then
      begin
        ans:=a[mid];
        l:=mid+;
      end
      else r:=mid-;
    end;
    writeln(ans);
  end;
end.

bzoj2653的更多相关文章

  1. BZOJ2653 middle(二分答案+主席树)

    与中位数有关的题二分答案是很常用的trick.二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0. 由于每个位置是1还是-1并不固定,似乎不是很好算.考 ...

  2. 【BZOJ2653】Middle(主席树)

    [BZOJ2653]Middle(主席树) 题面 BZOJ 洛谷 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你 ...

  3. BZOJ2653 middle 【主席树】【二分】*

    BZOJ2653 middle Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样 ...

  4. 【BZOJ2653】middle 二分+可持久化线段树

    [BZOJ2653]middle Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个 ...

  5. [bzoj2653][middle] (二分 + 主席树)

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

  6. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  7. bzoj2653: middle

    首先,对于每个询问,我们二分答案 然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1 那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁 这个区间和呢,我们可以用主席树维 ...

  8. bzoj2653:middle

    思路:首先容易想到二分答案,但如何去check呢,对于一段区间[l,r],把所有小于答案的都赋值为-1,大于等于它的都赋值为1,然后求左端点在[a,b],右端点在[c,d]的最大子串和即可(也就是区间 ...

  9. 【BZOJ2653】【主席树+二分】middle

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

随机推荐

  1. Linux下安装GAMS建模优化工具

    1.下载GAMS wget http://d37drm4t2jghv5.cloudfront.net/distributions/24.5.6/linux/linux_x64_64_sfx.exe 2 ...

  2. 一个玩具程序——测试密码强度(pure C)

    替人写的C语言作业… 介绍: 程序名称:密码强度检测程序 注释风格:doxygen 测试环境:linux3.6, gcc4.7window7, vs2012 已知问题:1. 算法与参考链接不一致,结果 ...

  3. (转)VS自带工具:dumpbin的使用

    有时候我们想查看一个exe引用了哪些动态库,或者我们想看某个动态库包含哪些接口函数,这个时候可以使用dumpbin.exe工具: 1.输入Dumpbin -imports calldll.exe查看它 ...

  4. Java文件操作二:File文件的方法

    一.文件的判断方法 判断方法 .boolean canExecute()判断文件是否可执行 .boolean canRead()判断文件是否可读 .boolean canWrite() 判断文件是否可 ...

  5. VS2008 未找到编译器可执行文件 csc.exe【当网上其他方法试玩了之后不起作用的时候再用这个方法】

    被公司派遣到中国海洋石油惠州炼化公司做项目,做的是生产管理,来了发现他们的项目结构简直烂的要命,和同学们写的毕业设计差不多,然后开发工具用的是vs2008,我电脑是安装了vs2005和vs2010,v ...

  6. iOS-UI控件精讲之UIView

    道虽迩,不行不至:事虽小,不为不成. 相关阅读 1.iOS-UI控件精讲之UIView(本文) 2.iOS-UI控件精讲之UILabel ...待续 UIView是所有UI控件的基类,在布局的时候通常 ...

  7. IOS LocationManager定位国内偏移,火星坐标(GCJ-02)解决方法

    转载自:http://blog.csdn.net/swingpyzf/article/details/16972351 纠偏也可参考:http://www.2cto.com/kf/201310/253 ...

  8. JSONP技术原理及实现

    跨域问题一直是前端中常见的问题,每当说到跨域,第一浮现的技术必然就是JSONP JSONP在我的理解,它并不是ajax,它是在文档中插入一个script标签,创建_callback方法,通过服务器配合 ...

  9. [转载] CMake Official Tutorial——教程还是官方的好

    CMake官方教程传送门:https://cmake.org/cmake-tutorial/ 以下的内容跟官方教程基本一致,少数地方根据自己的测试有所改动: A Basic Starting Poin ...

  10. BitMap(比特位)

    所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省. 腾讯面试的时候,让写了一个BitMap ...