【BZOJ2653】middle(主席树,二分)

题意:一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
  给你一个长度为n的序列s。
  回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
  其中a<b<c<d。
  位置也从0开始标号。
  我会使用一些方式强制你在线。

n<=20000,Q<=25000

思路:RYZ上课讲的题,第一次做这种类型的主席树,以前只会序列第K大,树上第K大,维护二维前缀和之类的……

这道题的精髓是用主席树保存每个点被更改后的N个版本

对于一段区间与一个数X,如果区间中的数a[i]>=x则b[i]=1,否则-1

易得:若某一段中b[i]总和>=0则必定可以从其中取出一段中位数为X的序列,则X可以作为答案

反之显然答案具有单调性,子段和最大的一段一定可以构造出最大的中位数

查询时判断queryr(a,b)+querysum(b+1,c-1)+queryl(c,d)是否>=0即可

剩下的二分X与最大子段和,最大左右子段和维护部分已经在各种各样的地方(NOI Plus模拟赛)做了不下10遍了

而且还有各种写法不同难度的,比如暴力,RMQ之类的

这题就是单点修改+线段树版本的

强制从0开始标号P党表示不爽

  1 var t:array[0..8100000,0..1]of longint;
  2     root,lx,rx,sum:array[0..8100000]of longint;
  3     a,b,d:array[1..30000]of longint;
  4     n,que,i,j,cnt,l,r,last,lastans,mid:longint;
  5 
  6 function max(x,y:longint):longint;
  7 begin
  8  if x>y then exit(x);
  9  exit(y);
 10 end;
 11 
 12 procedure swap(var x,y:longint);
 13 var t:longint;
 14 begin
 15  t:=x; x:=y; y:=t;
 16 end;
 17 
 18 procedure qsort(l,r:longint);
 19 var i,j,mid:longint;
 20 begin
 21  i:=l; j:=r; mid:=a[(l+r)>>1];
 22  repeat
 23   while mid>a[i] do inc(i);
 24   while mid<a[j] do dec(j);
 25   if i<=j then
 26   begin
 27    swap(a[i],a[j]);
 28    swap(b[i],b[j]);
 29    inc(i); dec(j);
 30   end;
 31  until i>j;
 32  if l<j then qsort(l,j);
 33  if i<r then qsort(i,r);
 34 end;
 35 
 36 procedure sort;
 37 var i,j:longint;
 38 begin
 39  for i:=1 to 3 do
 40   for j:=1 to 4-i do
 41    if d[j]>d[j+1] then swap(d[j],d[j+1]);
 42 end;
 43 
 44 procedure pushup(p:longint);
 45 var l,r:longint;
 46 begin
 47  l:=t[p,0]; r:=t[p,1];
 48  lx[p]:=max(lx[l],sum[l]+lx[r]);
 49  rx[p]:=max(rx[r],sum[r]+rx[l]);
 50  sum[p]:=sum[l]+sum[r];
 51 end;
 52 
 53 procedure build(var p:longint;l,r:longint);
 54 var mid:longint;
 55 begin
 56  inc(cnt); p:=cnt;
 57  if l=r then
 58  begin
 59   lx[p]:=1; rx[p]:=1; sum[p]:=1;
 60   exit;
 61  end;
 62  mid:=(l+r)>>1;
 63  build(t[p,0],l,mid);
 64  build(t[p,1],mid+1,r);
 65  pushup(p);
 66 end;
 67 
 68 procedure update(l,r:longint;var p:longint;v,x:longint);
 69 var mid:longint;
 70 begin
 71  inc(cnt); t[cnt]:=t[p]; lx[cnt]:=lx[p]; rx[cnt]:=rx[p]; sum[cnt]:=sum[p];
 72  p:=cnt;
 73  if l=r then
 74  begin
 75   sum[p]:=x; lx[p]:=x; rx[p]:=x;
 76   exit;
 77  end;
 78  mid:=(l+r)>>1;
 79  if v<=mid then update(l,mid,t[p,0],v,x)
 80   else update(mid+1,r,t[p,1],v,x);
 81  pushup(p);
 82 end;
 83 
 84 function querysum(l,r,x,y,p:longint):longint;
 85 var mid,s:longint;
 86 begin
 87  if (l=x)and(r=y) then exit(sum[p]);
 88  mid:=(l+r)>>1;
 89  s:=0;
 90  if y<=mid then s:=querysum(l,mid,x,y,t[p,0])
 91   else if x>mid then s:=querysum(mid+1,r,x,y,t[p,1])
 92    else s:=querysum(l,mid,x,mid,t[p,0])+
 93            querysum(mid+1,r,mid+1,y,t[p,1]);
 94  exit(s);
 95 end;
 96 
 97 function queryleft(l,r,x,y,p:longint):longint;
 98 var mid,s:longint;
 99 begin
100  if (l=x)and(r=y) then exit(lx[p]);
101  mid:=(l+r)>>1;
102  s:=0;
103  if y<=mid then s:=queryleft(l,mid,x,y,t[p,0])
104   else if x>mid then s:=queryleft(mid+1,r,x,y,t[p,1])
105    else s:=max(queryleft(l,mid,x,mid,t[p,0]),
106                querysum(l,mid,x,mid,t[p,0])+
107                queryleft(mid+1,r,mid+1,y,t[p,1]));
108  exit(s);
109 end;
110 
111 function queryright(l,r,x,y,p:longint):longint;
112 var mid,s:longint;
113 begin
114  if (l=x)and(r=y) then exit(rx[p]);
115  mid:=(l+r)>>1;
116  s:=0;
117  if y<=mid then s:=queryright(l,mid,x,y,t[p,0])
118   else if x>mid then s:=queryright(mid+1,r,x,y,t[p,1])
119    else s:=max(queryright(mid+1,r,mid+1,y,t[p,1]),
120                querysum(mid+1,r,mid+1,y,t[p,1])+
121                queryright(l,mid,x,mid,t[p,0]));
122  exit(s);
123 end;
124 
125 function isok(k,a,b,c,d:longint):boolean;
126 var s:longint;
127 begin
128  s:=0;
129  if b+1<=c-1 then s:=querysum(0,n-1,b+1,c-1,root[k]);
130  s:=s+queryright(0,n-1,a,b,root[k]);
131  s:=s+queryleft(0,n-1,c,d,root[k]);
132  exit(s>=0);
133 end;
134 
135 begin
136 
137  read(n);
138  for i:=1 to n do
139  begin
140   read(a[i]); b[i]:=i;
141  end;
142  qsort(1,n);
143 
144  build(root[0],0,n-1);
145  for i:=1 to n do
146  begin
147   root[i]:=root[i-1];
148   update(0,n-1,root[i],b[i]-1,-1);
149  end;
150  read(que);
151  for i:=1 to que do
152  begin
153   for j:=1 to 4 do read(d[j]);
154   for j:=1 to 4 do d[j]:=(d[j]+lastans) mod n;
155   sort;
156   l:=0; r:=n; last:=0;
157   while l<=r do
158   begin
159    mid:=(l+r)>>1;
160    if isok(mid,d[1],d[2],d[3],d[4]) then begin last:=mid; l:=mid+1; end
161     else r:=mid-1;
162   end;
163   lastans:=a[last+1];
164   writeln(lastans);
165  end;
166 
167 end.

 

 

 

 

 

posted on 2017-01-18 21:16  myx12345  阅读(189)  评论(0编辑  收藏  举报

导航