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.