zoukankan      html  css  js  c++  java
  • BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)

    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=3196

    可以处理区间问题的平衡树.

    3196: Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2412  Solved: 986
    [Submit][Status][Discuss]

    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]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000


    2.序列中每个数的数据范围:[0,1e8]


    3.虽然原题没有,但事实上5操作的k可能为负数

    Source

    分析


    树套树.可以用线段树套Treap.人生第一道树套树的题...

    op1:如果在整区间,直接在该区间的treap上求解.否则分两个区间求解,然后相加.最后+1.

    op2:这个不太好直接做,可以二分,每次假定一个值,用这个值去做op1,以此求得一个rank=k+1的数,求rank=k的数等价与求这个数的前驱pre.

    op3:先删后加.

    op4&op5:如果在整区间,直接在该区间的treap上求解,否则分量个区间求解,pre取最大值,suc取最小值.注意有些数在有些区间可能找不到前驱/后驱,这时pre返回-INF,suc取INF.

    p.s.

    1.神一样的调了一下午....上午做完普通平衡树感觉自己好不熟练啊居然搞了一上午,中午敲完这个题以为能A,结果RE,之后就没救了...发现时remove函数的问题,也没找到问题在哪,在开始怀疑人生之前换回了白书上的写法,果然A了,再看看原来的写法也没什么错啊.于是重新写了一遍原来的方法,结果A了.然后开始找不同,后来发现是结构体里定义的小于号不知咋地不好使了...C++学得太渣,最后只好舍弃,改为手动判断大小了...也不知道问题出在哪,最后还是没有解决,好遗憾...

     1.白书上的remove写法

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int maxn=50000+5,oo=~0u>>1;
      7 int n,q;
      8 int a[maxn];
      9 struct Treap{
     10     struct node{
     11         node* ch[2];
     12         int v,r,s,c;
     13         node(int v,node* t):v(v){ ch[0]=ch[1]=t; r=rand(); s=c=1; }
     14         bool operator < (const node &rhs) const{ return r<rhs.r; }
     15         void push_up() { s=ch[0]->s+ch[1]->s+c; }
     16     }*root,*null;
     17     Treap(){
     18         null=new node(0,NULL);
     19         null->c=null->s=0; null->r=oo;
     20         root=null;
     21     }
     22     void rotate(node* &o,bool d){
     23         node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o;
     24         o->push_up(); k->push_up(); o=k;
     25     }
     26     void insert(node* &o,int x){
     27         if(o==null) o=new node(x,null);
     28         else{
     29             if(x==o->v){ o->s++; o->c++; }
     30             else{
     31                 bool d=x>o->v;
     32                 insert(o->ch[d],x);
     33                 if(o->ch[d]<o) rotate(o,!d);
     34                 o->push_up();
     35             }
     36         }
     37     }
     38     void remove(node* &o,int x){
     39         if(o->v==x){
     40             if(o->c>1) { o->c--; o->s--; }
     41             else{
     42                 if(o->ch[0]!=null&&o->ch[1]!=null){
     43                     bool d=o->ch[0]<o->ch[1];
     44                     rotate(o,d); remove(o->ch[d],x); o->push_up();
     45                 }
     46                 else{
     47                     node* u=o;
     48                     if(o->ch[0]==null) o=o->ch[1]; else o=o->ch[0];
     49                     delete u;
     50                 }
     51             }
     52         }
     53         else{
     54             bool d=x>o->v;
     55             remove(o->ch[d],x);
     56             o->push_up();
     57         }
     58     }
     59     int rank(int x){
     60         int ret=0,s;
     61         for(node *t=root;t!=null;){
     62             s=t->ch[0]->s+t->c;
     63             if(x>t->v) ret+=s,t=t->ch[1];
     64             else t=t->ch[0];
     65         }
     66         return ret;
     67     }
     68     int pre(int x){
     69         int ret=-oo;
     70         for(node* t=root;t!=null;){
     71             if(t->v<x) ret=t->v,t=t->ch[1];
     72             else t=t->ch[0];
     73         }
     74         return ret;
     75     }
     76     int suc(int x){
     77         int ret=oo;
     78         for(node* t=root;t!=null;){
     79             if(t->v>x) ret=t->v,t=t->ch[0];
     80             else t=t->ch[1];
     81             }
     82         return ret;
     83     }
     84 };
     85 
     86 struct Segment_Tree{
     87     Treap tree[maxn*3];
     88     void build_tree(int l,int r,int k){
     89         for(int i=l;i<=r;i++) tree[k].insert(tree[k].root,a[i]);
     90         if(l==r) return;
     91         int mid=l+((r-l)>>1);
     92         build_tree(l,mid,k<<1); build_tree(mid+1,r,k<<1|1);
     93     }
     94     int get_rank(int l,int r,int k,int x,int y,int X){
     95         if(l==x&&r==y) return tree[k].rank(X);
     96         int mid=l+((r-l)>>1);
     97         if(y<=mid) return get_rank(l,mid,k<<1,x,y,X);
     98         else if(x>mid) return get_rank(mid+1,r,k<<1|1,x,y,X);
     99         else return get_rank(l,mid,k<<1,x,mid,X)+get_rank(mid+1,r,k<<1|1,mid+1,y,X);
    100     }
    101     void change(int l,int r,int k,int id,int x){
    102         tree[k].remove(tree[k].root,a[id]);
    103         tree[k].insert(tree[k].root,x);
    104         if(l==r) return;
    105         int mid=l+((r-l)>>1);
    106         if(id<=mid) change(l,mid,k<<1,id,x);
    107         else change(mid+1,r,k<<1|1,id,x);
    108     }
    109     int get_pre(int l,int r,int k,int x,int y,int X){
    110         if(l==x&&r==y) return tree[k].pre(X);
    111         int mid=l+((r-l)>>1);
    112         if(y<=mid) return get_pre(l,mid,k<<1,x,y,X);
    113         else if(x>mid) return get_pre(mid+1,r,k<<1|1,x,y,X);
    114         else return max(get_pre(l,mid,k<<1,x,mid,X),get_pre(mid+1,r,k<<1|1,mid+1,y,X));
    115     }
    116     int get_suc(int l,int r,int k,int x,int y,int X){
    117         if(l==x&&r==y) return tree[k].suc(X);
    118         int mid=l+((r-l)>>1);
    119         if(y<=mid) return get_suc(l,mid,k<<1,x,y,X);
    120         else if(x>mid) return get_suc(mid+1,r,k<<1|1,x,y,X);
    121         else return min(get_suc(l,mid,k<<1,x,mid,X),get_suc(mid+1,r,k<<1|1,mid+1,y,X));
    122     }
    123     int get_kth(int x,int y,int k){
    124         int l=0,r=oo;
    125         while(l<r){
    126             int mid=l+((r-l)>>1);
    127             int tmp=get_rank(1,n,1,x,y,mid)+1;
    128             if(tmp<=k) l=mid+1;
    129             else r=mid;
    130         }
    131         return get_pre(1,n,1,x,y,l);
    132     }
    133 }T;
    134 
    135 int main()
    136 {
    137     scanf("%d%d",&n,&q);
    138     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    139     T.build_tree(1,n,1);
    140     int qry,l,r,k,x,pos;
    141     for(int i=1;i<=q;i++){
    142         scanf("%d",&qry);
    143         switch(qry){
    144             case 1:
    145                 scanf("%d%d%d",&l,&r,&x);
    146                 printf("%d
    ",T.get_rank(1,n,1,l,r,x)+1);break;
    147             case 2:
    148                 scanf("%d%d%d",&l,&r,&k);
    149                 printf("%d
    ",T.get_kth(l,r,k));break;
    150             case 3:
    151                 scanf("%d%d",&pos,&x);
    152                 T.change(1,n,1,pos,x);
    153                 a[pos]=x;break;
    154             case 4:
    155                 scanf("%d%d%d",&l,&r,&x);
    156                 printf("%d
    ",T.get_pre(1,n,1,l,r,x));break;
    157             case 5:
    158                 scanf("%d%d%d",&l,&r,&x);
    159                 printf("%d
    ",T.get_suc(1,n,1,l,r,x));break;
    160         }
    161     }
    162     return 0;
    163 }
    View Code

     2.另一种remove写法

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <algorithm>
      4 using namespace std;
      5      
      6 const int maxn=50000+5,oo=~0u>>1;
      7 int n,q;
      8 int a[maxn];
      9 struct Treap{
     10     struct node{
     11         node* ch[2];
     12         int v,r,s,c;
     13         node(int v,node* t):v(v){ ch[0]=ch[1]=t; r=rand(); s=c=1; }
     14         void push_up() { s=ch[0]->s+ch[1]->s+c; }
     15     }*root,*null;
     16     Treap(){
     17         null=new node(0,NULL);
     18         null->c=null->s=0; null->r=oo;
     19         root=null;
     20     }
     21     void rotate(node* &o,bool d){
     22         node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o;
     23         o->push_up(); k->push_up(); 
     24         if(o==root) root=k;
     25         o=k;
     26     }
     27     void insert(node* &o,int x){
     28         if(o==null) o=new node(x,null);
     29         else{
     30             if(x==o->v)  o->s++, o->c++;
     31             else{
     32                 bool d=x>o->v;
     33                 insert(o->ch[d],x);
     34                 if(o->ch[d]<o) rotate(o,!d);
     35                 o->push_up();
     36             }
     37         }
     38     }
     39     void remove(node* &o,int x) {
     40         if(x==o->v) {
     41             if(o->c>1) o->c--,o->s--;           
     42             else{
     43                 bool d=o->ch[1]->r<o->ch[0]->r;
     44                 if(o->ch[d]==null){
     45                     delete o;
     46                     o=null;
     47                 }
     48                 else{
     49                     rotate(o,!d);
     50                     remove(o->ch[!d],x);
     51                     o->push_up();
     52                 }
     53             }
     54         }
     55         else{
     56             bool d=x>o->v;
     57             remove(o->ch[d],x);
     58             o->push_up();
     59         }
     60     }
     61     int rank(int x){
     62         int ret=0,s;
     63         for(node *t=root;t!=null;){
     64             s=t->ch[0]->s+t->c;
     65             if(x>t->v) ret+=s,t=t->ch[1];
     66             else t=t->ch[0];
     67         }
     68         return ret;
     69     }
     70     int pre(int x){
     71         int ret=-oo;
     72         for(node* t=root;t!=null;){
     73             if(t->v<x) ret=t->v,t=t->ch[1];
     74             else t=t->ch[0];
     75         }
     76         return ret;
     77     }
     78     int suc(int x){
     79         int ret=oo;
     80         for(node* t=root;t!=null;){
     81             if(t->v>x) ret=t->v,t=t->ch[0];
     82             else t=t->ch[1];
     83             }
     84         return ret;
     85     }
     86 };
     87      
     88 struct Segment_Tree{
     89     Treap tree[maxn<<2];
     90     void build_tree(int l,int r,int k){
     91         for(int i=l;i<=r;i++) tree[k].insert(tree[k].root,a[i]);
     92         if(l==r) return;
     93         int mid=l+((r-l)>>1);
     94         build_tree(l,mid,k<<1); build_tree(mid+1,r,k<<1|1);
     95     }
     96     int get_rank(int l,int r,int k,int x,int y,int X){
     97         if(l==x&&r==y) return tree[k].rank(X);
     98         int mid=l+((r-l)>>1);
     99         if(y<=mid) return get_rank(l,mid,k<<1,x,y,X);
    100         else if(x>mid) return get_rank(mid+1,r,k<<1|1,x,y,X);
    101         else return get_rank(l,mid,k<<1,x,mid,X)+get_rank(mid+1,r,k<<1|1,mid+1,y,X);
    102     }
    103     void change(int l,int r,int k,int id,int x){
    104         tree[k].remove(tree[k].root,a[id]);
    105         tree[k].insert(tree[k].root,x);
    106         if(l==r) return;
    107         int mid=l+((r-l)>>1);
    108         if(id<=mid) change(l,mid,k<<1,id,x);
    109         else change(mid+1,r,k<<1|1,id,x);
    110     }
    111     int get_pre(int l,int r,int k,int x,int y,int X){
    112         if(l==x&&r==y) return tree[k].pre(X);
    113         int mid=l+((r-l)>>1);
    114         if(y<=mid) return get_pre(l,mid,k<<1,x,y,X);
    115         else if(x>mid) return get_pre(mid+1,r,k<<1|1,x,y,X);
    116         else return max(get_pre(l,mid,k<<1,x,mid,X),get_pre(mid+1,r,k<<1|1,mid+1,y,X));
    117     }
    118     int get_suc(int l,int r,int k,int x,int y,int X){
    119         if(l==x&&r==y) return tree[k].suc(X);
    120         int mid=l+((r-l)>>1);
    121         if(y<=mid) return get_suc(l,mid,k<<1,x,y,X);
    122         else if(x>mid) return get_suc(mid+1,r,k<<1|1,x,y,X);
    123         else return min(get_suc(l,mid,k<<1,x,mid,X),get_suc(mid+1,r,k<<1|1,mid+1,y,X));
    124     }
    125     int get_kth(int x,int y,int k){
    126         int l=0,r=oo;
    127         while(l<r){
    128             int mid=l+((r-l)>>1);
    129             int tmp=get_rank(1,n,1,x,y,mid)+1;
    130             if(tmp<=k) l=mid+1;
    131             else r=mid;
    132         }
    133         return get_pre(1,n,1,x,y,l);
    134     }
    135 }T;
    136      
    137 int main()
    138 {
    139     scanf("%d%d",&n,&q);
    140     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    141     T.build_tree(1,n,1);
    142     int qry,l,r,k,x,pos;
    143     for(int i=1;i<=q;i++){
    144         scanf("%d",&qry);
    145         switch(qry){
    146             case 1:
    147                 scanf("%d%d%d",&l,&r,&x);
    148                 printf("%d
    ",T.get_rank(1,n,1,l,r,x)+1);break;
    149             case 2:
    150                 scanf("%d%d%d",&l,&r,&k);
    151                 printf("%d
    ",T.get_kth(l,r,k));break;
    152             case 3:
    153                 scanf("%d%d",&pos,&x);
    154                 T.change(1,n,1,pos,x);
    155                 a[pos]=x;break;
    156             case 4:
    157                 scanf("%d%d%d",&l,&r,&x);
    158                 printf("%d
    ",T.get_pre(1,n,1,l,r,x));break;
    159             case 5:
    160                 scanf("%d%d%d",&l,&r,&x);
    161                 printf("%d
    ",T.get_suc(1,n,1,l,r,x));break;
    162         }
    163     }
    164     return 0;
    165 }
    View Code
  • 相关阅读:
    Binary Search Tree Iterator 解答
    Invert Binary Tree 解答
    Min Stack 解答
    Trapping Raining Water 解答
    Candy 解答
    Jump Game II 解答
    Implement Hash Map Using Primitive Types
    Gas Station 解答
    Bucket Sort
    HashMap 专题
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5483942.html
Copyright © 2011-2022 走看看