Hustoj (poj2104)线段树(划分树)
来源:互联网 发布:淘宝宝贝图片拍摄技巧 编辑:程序博客网 时间:2024/06/05 12:02
昨天做hust线段树专题的时候,可是不懂,后来查了网上的解题报告,才知道是应用划分树来计算的,因此这两天就学习划分树,
按照我个人的理解,划分树其基本思想就是通过如下的步骤
1.增加一个数组,将原来的数组信息排序号放在该数组上
2.建立一个课线段树(是根据排好序的数组来的),取中间的数字,把小于该数字的加入到左子树中,大于的加入到右子树中去,同时以一个二维数组来记录在该数之前有多少个数字已经加入到左子树中去(是为了后面查询的操作)
3.查询
通过LINK:http://vjudge.net/vjudge/contest/view.action?cid=57851#problem/E
就是poj的2104的题目来解释
下面这个是带有详细解释的代码
#define M 100001struct Seg_Tree{ int left,right; int mid() { return (left + right) >> 1; }}tt[M*4];int len;int sorted[M];int toLeft[20][M];int val[20][M]; void build(int l,int r,int d,int idx) //build(1,n,0,1); { tt[idx].left = l; tt[idx].right = r; if(tt[idx].left == tt[idx].right) return ; int mid = tt[idx].mid(); int lsame = mid - l + 1;//lsame表示和val_mid相等且分到左边的 for(int i = l ; i <= r ; i ++) { if(val[d][i] < sorted[mid]) { lsame --;//先假设左边的数(mid - l + 1)个都等于val_mid,然后把实际上小于val_mid的减去 } } int lpos = l; int rpos = mid+1; int same = 0; for(int i = l ; i <= r ; i ++) { if(i == l) { toLeft[d][i] = 0;//toLeft[i]表示[ tt[idx].left , i ]区域里有多少个数分到左边 } else { toLeft[d][i] = toLeft[d][i-1]; } if(val[d][i] < sorted[mid]) { toLeft[d][i] ++; val[d+1][lpos++] = val[d][i]; } else if(val[d][i] > sorted[mid]) { val[d+1][rpos++] = val[d][i]; } else { if(same < lsame) {//有lsame的数是分到左边的 same ++; toLeft[d][i] ++; val[d+1][lpos++] = val[d][i]; } else { val[d+1][rpos++] = val[d][i]; } } } build(l,mid,d+1,LL(idx)); build(mid+1,r,d+1,RR(idx));} int query(int l,int r,int k,int d,int idx) { if(l == r) { return val[d][l]; } int s;//s表示[ l , r ]有多少个分到左边 int ss;//ss表示 [tt[idx].left , l-1 ]有多少个分到左边 if(l == tt[idx].left) { s = toLeft[d][r]; ss = 0; } else { s = toLeft[d][r] - toLeft[d][l-1]; ss = toLeft[d][l-1]; } if(s >= k) { //有多于k个分到左边,显然去左儿子区间找第k个 int newl = tt[idx].left + ss; int newr = tt[idx].left + ss + s - 1;//计算出新的映射区间,这里减去1是因为那个tt【idx】+ss已经包含了[l,r]中的数,因此要减去1 return query(newl,newr,k,d+1,LL(idx)); } else //s<k;就是说左边的数不够,因此要到右边去找 { int mid = tt[idx].mid(); int bb = l - tt[idx].left - ss;//bb表示 [tt[idx].left , l-1 ]有多少个分到右边 int b = r - l + 1 - s;//b表示 [l , r]有多少个分到右边 int newl = mid + bb + 1; int newr = mid + bb + b; return query(newl,newr,k-s,d+1,RR(idx)); }} int main() { int T; scanf("%d",&T); while(T --) { int n , m; scanf("%d%d",&n,&m); FOR(i,1,n+1) { scanf("%d",&val[0][i]); sorted[i] = val[0][i]; } sort(sorted + 1 , sorted + n + 1); build(1,n,0,1); while(m --) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(l,r,k,0,1)); } } return 0;}
AC CODE
#include<stdio.h>#include<iostream>#include<algorithm>using namespace std;#define M 100010struct Seg_Tree{ int left,right;int mid(){ return (left+right)>>1;} }tt[M*4];int len;int sorted[M];int toLeft[20][M];int val[20][M];void build(int l,int r,int d,int idx){ tt[idx].left=l; tt[idx].right=r; if(tt[idx].left==tt[idx].right) return; int mid=tt[idx].mid(); int Isame=mid-l+1; for(int i=l;i<=r;i++) { if(val[d][i]<sorted[mid]) Isame--; } int lpos=l; int rpos=mid+1; int same=0; for(int i=l;i<=r;i++) { if(i==l) { toLeft[d][i]=0; } else { toLeft[d][i]=toLeft[d][i-1]; } if(val[d][i]<sorted[mid]) { toLeft[d][i]++; val[d+1][lpos++]=val[d][i]; } else if(val[d][i]>sorted[mid]) { val[d+1][rpos++]=val[d][i]; } else { if(same<Isame) { same++; toLeft[d][i]++; val[d+1][lpos++]=val[d][i]; } else { val[d+1][rpos++]=val[d][i];} } } build(l,mid,d+1,idx*2); build(mid+1,r,d+1,idx*2+1);}int query(int l, int r, int k, int d, int idx){ if(l==r) return val[d][l]; int s; int ss; if(l==tt[idx].left) { s=toLeft[d][r]; ss=0; } else { s=toLeft[d][r]-toLeft[d][l-1]; ss=toLeft[d][l-1]; } if(s>=k) { int newl=tt[idx].left+ss; int newr=tt[idx].left+ss+s-1; return query(newl,newr,k,d+1,idx*2); } else { int mid=tt[idx].mid(); int bb=l-tt[idx].left-ss; int b=r-l+1-s; int newl=mid+bb+1; int newr=mid+bb+b; return query(newl,newr,k-s,d+1,idx*2+1); }}int main(void){ int n,m; while(scanf("%d %d",&n,&m)!=EOF) {for(int i=1;i<=n;i++){ scanf("%d",&val[0][i]); sorted[i]=val[0][i];}sort(sorted+1,sorted+n+1);build(1,n,0,1);while(m--){ int a, b,c; scanf("%d %d %d",&a,&b,&c); printf("%d\n",query(a,b,c,0,1)); } } return 0;}
继续学习线段树!KEEP IT ON
0 0
- Hustoj (poj2104)线段树(划分树)
- 划分树(模板)poj2104
- poj2104 K-th Number(划分树)
- (划分树)poj2104 K-th Number
- poj2104 划分树
- poj2104(划分树)
- poj2104 hdu2665 划分树
- 划分树 poj2104 hdu5249
- 划分树 POJ2104
- poj2104[划分树问题]
- HUSTOJ 2867: 火车票(线段树)
- poj2104——K-th Number(划分树)
- POJ2104 K-th Number (划分树模板)
- 线段树基础 poj2104
- 【线段树专题】poj2104
- 185_K-th NUmber 线段树 (POJ2104)
- poj2104 线段树+二分搜索
- poj2104||hdu2665 归并树|划分树
- [欧拉回路+手动开栈] poj 1780 Code
- leetcode-Largest Rectangular Area in a Histogram
- UVA - 11044 Searching for Nessy
- Harvard statistics 110, video 8 note(random variables & their distribution
- 关于程序员成长的一点思考
- Hustoj (poj2104)线段树(划分树)
- erlang 实现list的二分查找
- 数据结构 第二章 线性表 思维导图
- Codeforces Round #271 (Div. 2) B
- struts2.x加入百度ueditor在线编辑框
- strcpy
- iOS常用设计模式——原型模式
- UVA10010
- RTC没有工作的原因分析