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
  • 相关阅读:
    (五)CSS和JavaScript基础
    (四)标签框架
    (三)表单与servlet的初步结合
    (三)文档结构(上)
    (二十一)持有对象以及泛型基础(1)
    (二十)内部类详解(转)
    (十九)接口类型的简介
    nginx配置文件
    nginx负载均衡
    debian iptables持久化
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5483942.html
Copyright © 2011-2022 走看看