• 【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.

     

  • 相关阅读:
    科学使用睡眠周期,你会比别人拥有更多时间
    遇见那个对的人,便是爱情
    因为专注,所以伟大
    从来都没有爱情发生的人生
    每天只要做好三件事就行了 积跬步以至千里
    不读书的中国人
    两性思维的差异与情侣夫妻间争吵
    结婚的意义 — 几米
    二维码工具类
    验证码图片生成工具类——Captcha.java
  • 原文地址:https://www.cnblogs.com/myx12345/p/6298173.html
Copyright © 2020-2023  润新知