首页 > 代码库 > BZOJ 3196

BZOJ 3196

program bzoj3196;const inf=100000000;    maxn=200001;    maxm=3000001;var n,m,time,temp:longint;    root,a:array [0..maxn] of longint;    left,right,rnd,v,s,w:array [0..maxm] of longint;procedure update(now:longint);begin    s[now]:=s[left[now]]+s[right[now]]+w[now];end;procedure rightturn(var now:longint);var t:longint;begin    t:=left[now];    left[now]:=right[t];    right[t]:=now;    s[t]:=s[now];    update(now);    now:=t;end;procedure leftturn(var now:longint);var t:longint;begin    t:=right[now];    right[now]:=left[t];    left[t]:=now;    s[t]:=s[now];    update(now);    now:=t;end;procedure insert(var now:longint; num:longint);begin  if now=0 then     begin      inc(time);      now:=time;      w[now]:=1;      s[now]:=w[now];      v[now]:=num;      rnd[now]:=random(inf);      exit;    end;   inc(s[now]);   if num=v[now] then inc(w[now])   else if num<v[now] then       begin        insert(left[now],num);          if rnd[left[now]]<rnd[now] then rightturn(now);      end    else        begin        insert(right[now],num);        if rnd[right[now]]<rnd[now] then leftturn(now);      end;end;procedure del(var now:longint; num:longint);begin  if v[now]=num then     begin      if w[now]>1 then         begin          dec(w[now]);          dec(s[now]);          exit;        end;      if left[now]*right[now]=0 then         now:=left[now]+right[now]      else         if rnd[left[now]]<rnd[right[now]] then           begin            rightturn(now);            del(now,num);          end      else           begin          leftturn(now);          del(now,num);        end    end   else       if num<v[now] then        begin         del(left[now],num);         dec(s[now]);       end    else       begin        del(right[now],num);        dec(s[now]);      end;end;procedure build(now,l,r,x,num:longint);var mid:longint;begin  insert(root[now],num);  if l=r then exit;  mid:=(l+r) shr 1;  if x<=mid then build(now<<1,l,mid,x,num)  else build(now<<1 or 1,mid+1,r,x,num);end;procedure ask_rank(now,num:longint);begin  if now=0 then exit;  if num=v[now] then     begin      inc(temp,s[left[now]]);      exit;    end  else      if num<v[now] then      ask_rank(left[now],num)  else    begin      inc(temp,s[left[now]]+w[now]);      ask_rank(right[now],num);    end;end;procedure get_rank(now,l,r,x,y,num:longint);var mid:longint;begin  mid:=(l+r) shr 1;  if (l=x) and (r=y) then     begin       ask_rank(root[now],num);      exit;    end;  if mid>=y then get_rank(now<<1,l,mid,x,y,num)  else if mid<x then get_rank(now<<1 or 1,mid+1,r,x,y,num)  else    begin      get_rank(now<<1,l,mid,x,mid,num);      get_rank(now<<1 or 1,mid+1,r,mid+1,y,num);    end;end;procedure get_index(x,y,z:longint);var l,r,ans,mid:longint;begin  l:=0; r:=inf;  while l<=r do    begin      mid:=(l+r) shr 1;      temp:=1;      get_rank(1,1,n,x,y,mid);      if temp<=z then         begin          l:=mid+1;          ans:=mid;        end      else         r:=mid-1;    end;  writeln(ans);end;procedure change(now,l,r,x,num,y:longint);var mid:longint;begin  del(root[now],y);  insert(root[now],num);  if l=r then exit;  mid:=(l+r) shr 1;  if x<=mid then change(now<<1,l,mid,x,num,y)  else change(now<<1 or 1,mid+1,r,x,num,y);end;function max(x,y:longint):longint;begin  if x>y then exit(x)  else exit(y);end;function min(x,y:longint):longint;begin  if x<y then exit(x)  else exit(y);end;procedure before(now,num:longint);begin  if now=0 then exit;  if v[now]<num then     begin      temp:=max(v[now],temp);      before(right[now],num);    end  else     before(left[now],num);end;procedure after(now,num:longint);begin  if now=0 then exit;  if v[now]>num then     begin      temp:=min(v[now],temp);      after(left[now],num);    end  else     after(right[now],num);end;procedure ask_after(now,l,r,x,y,num:longint);var mid:longint;begin  if (l=x) and (r=y) then     begin      after(root[now],num);      exit;    end;  mid:=(l+r) shr 1;  if mid>=y then ask_after(now<<1,l,mid,x,y,num)  else if mid<x then ask_after(now<<1 or 1,mid+1,r,x,y,num)  else     begin      ask_after(now<<1,l,mid,x,mid,num);      ask_after(now<<1 or 1,mid+1,r,mid+1,y,num);    end;end;procedure ask_before(now,l,r,x,y,num:longint);var mid:longint;begin  if (l=x) and (r=y) then     begin      before(root[now],num);      exit;    end;  mid:=(l+r) shr 1;  if mid>=y then ask_before(now<<1,l,mid,x,y,num)  else if mid<x then ask_before(now<<1 or 1,mid+1,r,x,y,num)  else     begin      ask_before(now<<1,l,mid,x,mid,num);      ask_before(now<<1 or 1,mid+1,r,mid+1,y,num);    end;end;procedure main;var i,x,y,now,f:longint;begin  read(n,m);  for i:=1 to n do read(a[i]);  for i:=1 to n do build(1,1,n,i,a[i]);  for i:=1 to m do    begin      read(f);      case f of         1:          begin            read(x,y,now);            temp:=1;            get_rank(1,1,n,x,y,now);            writeln(temp);          end;        2:          begin            read(x,y,now);            get_index(x,y,now);          end;        3:          begin            read(x,y);            change(1,1,n,x,y,a[x]);            a[x]:=y;          end;        4:          begin            read(x,y,now);            temp:=0;            ask_before(1,1,n,x,y,now);            writeln(temp);          end;        5:          begin            read(x,y,now);            temp:=inf;            ask_after(1,1,n,x,y,now);            writeln(temp);          end;      end;    end;end;begin  main;end.

 

BZOJ 3196