• bzoj2653


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

      1 type node=record
      2        lm,rm,l,r,s:longint;
      3      end;
      4 
      5 var tree:array[0..20010*20] of node;
      6     a,c,h:array[0..20010] of longint;
      7     q:array[0..4] of longint;
      8     j,m,t,ans,n,mid,i,l,r,w:longint;
      9 
     10 function max(a,b:longint):longint;
     11   begin
     12     if a>b then exit(a) else exit(b);
     13   end;
     14 
     15 procedure swap(var a,b:longint);
     16   var c:longint;
     17   begin
     18     c:=a;
     19     a:=b;
     20     b:=c;
     21   end;
     22 
     23 procedure deal;
     24   var i,j:longint;
     25   begin
     26     for i:=1 to 3 do
     27       for j:=i+1 to 4 do
     28         if q[i]>q[j] then swap(q[i],q[j]);
     29   end;
     30 
     31 procedure sort(l,r: longint);
     32   var i,j,x,y: longint;
     33   begin
     34     i:=l;
     35     j:=r;
     36     x:=a[(l+r) shr 1];
     37     repeat
     38       while a[i]<x do inc(i);
     39       while x<a[j] do dec(j);
     40       if not(i>j) then
     41       begin
     42         swap(c[i],c[j]);
     43         swap(a[i],a[j]);
     44         inc(i);
     45         j:=j-1;
     46       end;
     47     until i>j;
     48     if l<j then sort(l,j);
     49     if i<r then sort(i,r);
     50   end;
     51 procedure update(var a,b,c:node);
     52   begin
     53     a.s:=b.s+c.s;
     54     a.lm:=max(b.lm,b.s+c.lm);
     55     a.rm:=max(c.rm,c.s+b.rm);
     56   end;
     57 
     58 function build(l,r:longint):longint;
     59   var m,q:longint;
     60   begin
     61     inc(t);
     62     if l=r then
     63     begin
     64       tree[t].s:=1;
     65       tree[t].lm:=1;
     66       tree[t].rm:=1;
     67       exit(t);
     68     end
     69     else begin
     70       m:=(l+r) shr 1;
     71       q:=t;
     72       tree[q].l:=build(l,m);
     73       tree[q].r:=build(m+1,r);
     74       update(tree[q],tree[tree[q].l],tree[tree[q].r]);
     75       exit(q);
     76     end;
     77   end;
     78 
     79 function work(l,r,last,x:longint):longint;
     80   var m,q:longint;
     81   begin
     82     inc(t);
     83     if l=r then
     84     begin
     85       tree[t].s:=-1;
     86       tree[t].lm:=-1;
     87       tree[t].rm:=-1;
     88       exit(t);
     89     end
     90     else begin
     91       m:=(l+r) shr 1;
     92       q:=t;
     93       if x<=m then
     94       begin
     95         tree[q].r:=tree[last].r;
     96         tree[q].l:=work(l,m,tree[last].l,x);
     97       end
     98       else begin
     99         tree[q].l:=tree[last].l;
    100         tree[q].r:=work(m+1,r,tree[last].r,x);
    101       end;
    102       update(tree[q],tree[tree[q].l],tree[tree[q].r]);
    103       exit(q);
    104     end;
    105   end;
    106 
    107 function ask(l,r,x,ql,qr:longint):node;  //传递整个node的的写法比我以前的写法要简单不少
    108   var m:longint;
    109       s,s1,s2:node;
    110   begin
    111     s.lm:=0;  s.rm:=0;    s.s:=0;
    112     if ql>qr then exit(s);
    113     if (ql<=l) and (qr>=r) then exit(tree[x])
    114     else begin
    115       m:=(l+r) shr 1;
    116       if ql>m then exit(ask(m+1,r,tree[x].r,ql,qr));
    117       if qr<=m then exit(ask(l,m,tree[x].l,ql,qr));
    118       s1:=ask(l,m,tree[x].l,ql,qr);
    119       s2:=ask(m+1,r,tree[x].r,ql,qr);
    120       update(s,s1,s2);
    121       exit(s);
    122     end;
    123   end;
    124 
    125 begin
    126   readln(n);
    127   for i:=1 to n do
    128   begin
    129     readln(a[i]);
    130     c[i]:=i;
    131   end;
    132   sort(1,n);
    133   h[1]:=build(1,n);
    134   for i:=2 to n do
    135     h[i]:=work(1,n,h[i-1],c[i-1]);
    136   readln(m);
    137   for i:=1 to m do
    138   begin
    139     for j:=1 to 4 do
    140     begin
    141       read(q[j]);
    142       q[j]:=(q[j]+ans) mod n+1;
    143     end;
    144     readln;
    145     deal;
    146     l:=1;
    147     r:=n;
    148     while l<=r do  //二分答案
    149     begin
    150       mid:=(l+r) shr 1;
    151       w:=ask(1,n,h[mid],q[1],q[2]).rm+ask(1,n,h[mid],q[3],q[4]).lm+ask(1,n,h[mid],q[2]+1,q[3]-1).s;
    152       if w>=0 then
    153       begin
    154         ans:=a[mid];
    155         l:=mid+1;
    156       end
    157       else r:=mid-1;
    158     end;
    159     writeln(ans);
    160   end;
    161 end.
    View Code
  • 相关阅读:
    lvm新增脚本
    k8s 开源web操作平台
    ES6 对象数组查找某一个对象
    Git常用命令使用大全
    Failed to read session data On PHP 7.2
    解决Apache无法解析PHP问题
    使用apache htpasswd生成加密的密码文件,并使用.htaccess控制目录访问
    Apache开启关闭错误提示
    linux查找目录下的所有文件中是否含有某个字符串
    抖音60秒视频权限开通方法
  • 原文地址:https://www.cnblogs.com/phile/p/4473053.html
Copyright © 2020-2023  润新知