博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
求区间第K小值的两种解法:POJ2761
阅读量:5960 次
发布时间:2019-06-19

本文共 5096 字,大约阅读时间需要 16 分钟。

 前几天学习了划分树和SBT,一直没机会训练一下,今天实验室有网了,就训练POJ上面一道水题。分别用两种数据结构来实现了一下!

   这道题题目很简单,就是给定序列,求区间最小值!

   SBT:

 
  1. #include<stdio.h> 
  2. #include<algorithm> 
  3. using namespace std; 
  4. #define M 100005 
  5. struct SBT{ 
  6.     int key,left,right,size; 
  7. }tree[M]; 
  8. int root,top; 
  9.  
  10. int a[M]; 
  11. struct Query{ 
  12.     int ql,qr,k,id,ans; 
  13. }que[M/2]; 
  14. bool cmp(const Query &q1,const Query &q2){ 
  15.     if(q1.ql==q2.ql){ 
  16.         return q1.qr<q2.qr; 
  17.     } 
  18.     return q1.ql<q2.ql; 
  19. bool cmp2(const Query &q1,const Query &q2){ 
  20.     return q1.id<q2.id; 
  21. void init(){ 
  22.     root=top=0; 
  23. //这两种旋转看起来是挺容易的,但自己写容易混乱,最好能结合图 
  24. void rotate_left(int &x){ 
  25.     int y=tree[x].right; 
  26.     tree[x].right=tree[y].left; 
  27.     tree[y].left=x; 
  28.     tree[y].size=tree[x].size; 
  29.     tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; 
  30.     x=y; 
  31.  
  32. void rotate_right(int &x){ 
  33.     int y=tree[x].left; 
  34.     tree[x].left=tree[y].right; 
  35.     tree[y].right=x; 
  36.     tree[y].size=tree[x].size; 
  37.     tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; 
  38.     x=y; 
  39. void maintain(int &x,bool flag){ 
  40.     if(flag==false){
    //数据插入到左边了 
  41.         if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size){
    //情况 1 
  42.             //左孩子的左子树大于右孩子 
  43.             rotate_right(x); 
  44.         }else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size){ //情况 2 
  45.             rotate_left(tree[x].left);//先把树旋转成: 情况 1 
  46.             rotate_right(x);//按照情况1进行旋转 
  47.         }else return ; 
  48.     }else{
    //数据插入到右边了 
  49.         if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size){ 
  50.             rotate_left(x); 
  51.         }else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size){ 
  52.             rotate_right(tree[x].right); 
  53.             rotate_left(x); 
  54.         }else return ; 
  55.     } 
  56.     maintain(tree[x].left,false); 
  57.     maintain(tree[x].right,true); 
  58.     maintain(x,false); 
  59.     maintain(x,true); 
  60. /* 
  61.  * 这里用数组实现,递归插入,挺巧妙的,我自己用数组做的时候都不会想到这样做 
  62.  * tree的0位置空着不用; 帅气,如果不进行调整的话,root能保持root=1 
  63.  * */ 
  64. void insert(int &x,int key){ 
  65.     if(x==0){ 
  66.         x=++top;//确定插入的数组下标 
  67.         tree[x].left=tree[x].right=0; 
  68.         tree[x].key=key; 
  69.         tree[x].size=1; 
  70.     }else
  71.         tree[x].size++; 
  72.         if(key<=tree[x].key)//把相同的元素插入到左边 
  73.             insert(tree[x].left,key); 
  74.         else insert(tree[x].right,key); 
  75.         maintain(x,key>tree[x].key); 
  76.     } 
  77. //这里要保证删除的数据存在 
  78. void remove(int &x,int key){ 
  79.     tree[x].size--; 
  80.     if(key>tree[x].key){ 
  81.         remove(tree[x].right,key); 
  82.     }else if(key<tree[x].key){ 
  83.         remove(tree[x].left,key); 
  84.     }else
  85.         //有左子树,无右子树 
  86.         if(tree[x].left!=0&&tree[x].right==0){ 
  87.             x=tree[x].left; 
  88.             //无左子树,有右子树 
  89.         }else if(tree[x].right!=0&&tree[x].left==0){ 
  90.             x=tree[x].right; 
  91.         //叶子结点 
  92.         }else if(tree[x].left==0&&tree[x].right==0){ 
  93.             x=0; 
  94.             //有左子树,也有右子树 
  95.         }else
  96.             int temp=tree[x].right; 
  97.             while(tree[temp].left)temp=tree[temp].left; 
  98.             tree[x].key=tree[temp].key; 
  99.             remove(tree[x].right,tree[temp].key); 
  100.         } 
  101.     } 
  102. //求第k小的数 
  103. int select(int &x,int k){ 
  104.     int r=tree[tree[x].left].size+1; 
  105.     if(r==k)return tree[x].key; 
  106.     else if(r<k)return select(tree[x].right,k-r); 
  107.     else return select(tree[x].left,k); 
  108. int main(){ 
  109.     int n,m; 
  110.     int i,j; 
  111.     init(); 
  112.     scanf("%d %d",&n,&m); 
  113.     for(i=1;i<=n;i++){ 
  114.         scanf("%d",&a[i]); 
  115.     } 
  116.     int ql,qr,k; 
  117.     for(i=0;i<m;i++){ 
  118.         scanf("%d %d %d",&ql,&qr,&k); 
  119.         que[i].id=i; 
  120.         que[i].k=k; 
  121.         que[i].ql=ql; 
  122.         que[i].qr=qr; 
  123.     } 
  124.     sort(que,que+m,cmp); 
  125.     for(i=que[0].ql;i<=que[0].qr;i++){ 
  126.         insert(root,a[i]); 
  127.     } 
  128.     que[0].ans=select(root,que[0].k); 
  129.     for(i=1;i<m;i++){ 
  130.         //前一个区间与当前区间只有两种关系,相交或者不相交 
  131.         if(que[i].ql<=que[i-1].qr){ 
  132.             //看起点 
  133.             if(que[i].ql>que[i-1].ql){ 
  134.                 for(j=que[i-1].ql;j<que[i].ql;j++){ 
  135.                     remove(root,a[j]); 
  136.                 } 
  137.             } 
  138.             //看终点 
  139.             if(que[i].qr<que[i-1].qr){
    // 
  140.                 for(j=que[i].qr+1;j<=que[i-1].qr;j++){ 
  141.                     remove(root,a[j]); 
  142.                 } 
  143.             }else if(que[i].qr>que[i-1].qr){ 
  144.                 for(j=que[i-1].qr+1;j<=que[i].qr;j++){ 
  145.                     insert(root,a[j]); 
  146.                 } 
  147.             } 
  148.         }else
  149.             for(j=que[i-1].ql;j<=que[i-1].qr;j++){ 
  150.                 remove(root,a[j]); 
  151.             } 
  152.             for(j=que[i].ql;j<=que[i].qr;j++){ 
  153.                 insert(root,a[j]); 
  154.             } 
  155.         } 
  156.  
  157.         que[i].ans=select(root,que[i].k); 
  158.     } 
  159.     sort(que,que+m,cmp2); 
  160.     for(i=0;i<m;i++){ 
  161.         printf("%d\n",que[i].ans); 
  162.     } 
  163.     return 0; 

划分树:

 

 
  1. #include<stdio.h> 
  2. #include<algorithm> 
  3. using namespace std; 
  4. #define M 100005 
  5. int tree[30][M]; 
  6. int toLeft[30][M]; 
  7. int sorted[M]; 
  8.  
  9. int n,m; 
  10. void build(int level,int left,int right){ 
  11.     if(left==right)return
  12.     int mid=(left+right)>>1; 
  13.     int suppose; 
  14.     int i; 
  15.     suppose=mid-left+1; 
  16.     for(i=left;i<=right;i++){ 
  17.         if(tree[level][i]<sorted[mid]){ 
  18.             suppose--; 
  19.         } 
  20.     } 
  21.     int lpos=left,rpos=mid+1; 
  22.     for(i=left;i<=right;i++){ 
  23.         if(i==left){ 
  24.             toLeft[level][i]=0; 
  25.         }else
  26.             toLeft[level][i]=toLeft[level][i-1]; 
  27.         } 
  28.         if(tree[level][i]<sorted[mid]){ 
  29.             toLeft[level][i]++; 
  30.             tree[level+1][lpos++]=tree[level][i]; 
  31.         }else if(tree[level][i]>sorted[mid]){ 
  32.             tree[level+1][rpos++]=tree[level][i]; 
  33.         }else
  34.             if(suppose){ 
  35.                 suppose--; 
  36.                 toLeft[level][i]++; 
  37.                 tree[level+1][lpos++]=tree[level][i]; 
  38.             }else
  39.                 tree[level+1][rpos++]=tree[level][i]; 
  40.             } 
  41.         } 
  42.     } 
  43.     build(level+1,left,mid); 
  44.     build(level+1,mid+1,right); 
  45. int query(int level,int left,int right,int ql,int qr,int k){ 
  46.     if(ql==qr){ 
  47.         return tree[level][ql]; 
  48.     } 
  49.     int s,ss; 
  50.     int mid=(left+right)>>1; 
  51.     if(left==ql){ 
  52.         s=0; 
  53.         ss=toLeft[level][qr]; 
  54.     }else
  55.         s=toLeft[level][ql-1]; 
  56.         ss=toLeft[level][qr]-s; 
  57.     } 
  58.     int nql,nqr; 
  59.     if(k<=ss){ 
  60.         nql=left+s; 
  61.         nqr=left+s+ss-1; 
  62.         return query(level+1,left,mid,nql,nqr,k); 
  63.     }else
  64.         nql=mid-left+1+ql-s; 
  65.         nqr=mid-left+1+qr-s-ss; 
  66.         return query(level+1,mid+1,right,nql,nqr,k-ss); 
  67.     } 
  68.     return 0; 
  69. int main(){ 
  70.     scanf("%d %d",&n,&m); 
  71.     for(int i=1;i<=n;i++){ 
  72.         scanf("%d",&sorted[i]); 
  73.         tree[0][i]=sorted[i]; 
  74.     } 
  75.     sort(sorted+1,sorted+n+1); 
  76.     build(0,1,n); 
  77.     int ql,qr,k; 
  78.     for(int i=0;i<m;i++){ 
  79.         scanf("%d %d %d",&ql,&qr,&k); 
  80.         int ans=query(0,1,n,ql,qr,k); 
  81.         printf("%d\n",ans); 
  82.     } 
  83.  
  84.     return 0; 

 

转载地址:http://plkax.baihongyu.com/

你可能感兴趣的文章
Cocos2d-js-v3.2 在 mac 上配置环境以及编译到 Andorid 的注意事项(转)
查看>>
iOS用三种途径实现一方法有多个返回值
查看>>
python--class test
查看>>
从零开始理解JAVA事件处理机制(3)
查看>>
HttpURLConnection类的使用
查看>>
linux命令分析---SED (二)
查看>>
[INS-32025] 所选安装与指定 Oracle 主目录中已安装的软件冲突。
查看>>
py2与py3差别
查看>>
windows知识点
查看>>
第五章多态课后java_Java程序设计课后练习答案
查看>>
idea无用插件_没用过这些IDEA插件?怪不得写代码头疼
查看>>
linuxliveu盘怎么用_怎么用U盘重装系统?
查看>>
国际学院c语言作业,C语言程序的国际化
查看>>
四阶龙格库塔法c语言程序,四阶龙格库塔法C语言(西安交大)
查看>>
c语言中无windows函数库,关于C语言, GCC/MSVC中,如何写出一个真正意义上的不依赖库的程序?...
查看>>
欧洲语言框架A1到C2,法语等级 A1、A2、B1、B2、C1、C2
查看>>
c语言中以追加只写方式打开文本文件,C语言中打开文件读取,写入的操作
查看>>
c语言编程 企业发放,求c语言编程企业员工全年销售额统计及奖金发放系..._统计师_帮考网...
查看>>
C语言编辑中午和英语库,懂英语和C语言的来
查看>>
c语言cabd快速查询的方法,滨州医学院 数据结构C语言版习题精选
查看>>