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.
时间: 2024-11-07 02:52:06

BZOJ 3196的相关文章

[BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过128MB = = 嗯就是这样,代码长度= =我写了260行......Debug了n小时= = 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #in

BZOJ 3196 二逼平衡树

Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数,表示有序序列下面有m行,opt表示操作标号若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,

[BZOJ 3196] 二逼平衡树 树状数组套主席树

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3357  Solved: 1326[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为

BZOJ 3196 二逼平衡树 树套树

题目大意:...BZOJ挂了自己看去 好吧既然BZOJ挂了我还是贴上来吧0.0 破服务器 维护一种数据结构,提供下列操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,且最小的数) 其实一开始觉得这题是划分树主席树之类的 然后去了解了一下发现完全写不了... 后来才知道原来是树套树 以前想过线段树套树状数组 这数据范围别说树套树了连树状数组都开不开 正解应该是

【BZOJ 3196】Tyvj 1730 二逼平衡树

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 842  Solved: 350 [Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,

BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<ios

bzoj 3196 &amp;&amp; luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6372  Solved: 2406[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为

bzoj 3196: Tyvj 1730 二逼平衡树

我操,,,,我记得这个sb题,,搞了一整天,(吐槽,本来开心去洛谷提交,结果不一样,mdzz) 树套树,,,各种套... 都是在区间内最基本的查询 1 #include<bits/stdc++.h> 2 #define N 100005 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 inline int ra() 7 { 8 int x=0,f=1; char ch=getchar(); 9 w

BZOJ 3196 二逼平衡树 线段树+treap

题意:链接 方法:线段树+treap的模板题 题解: 首先是对于整个树的定义,其实treap部分并没有什么区别,只不过是单root改变为多root而已. #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define lson l,mid,rt<<1 #define rson mid+1,