划分树
2016-08-11 21:58
155 查看
虽然sunshine大神说划分树只是用来求第k小数这一个用处,但还是好好学习!!;
划分树建树的过程就是一个模拟快排的过程。
在建树的过程中,需要先取中间值,然后,小于中间值的放在左边,大于中间值的放在右边,在这个过程中,还需要记录第d层第i个树之前的左边的数。
poj 2104
下面写程序
划分树建树的过程就是一个模拟快排的过程。
在建树的过程中,需要先取中间值,然后,小于中间值的放在左边,大于中间值的放在右边,在这个过程中,还需要记录第d层第i个树之前的左边的数。
poj 2104
下面写程序
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 101000 using namespace std; struct node{ int s[maxn],c[maxn]; }; node t[50]; int a[maxn]; void build(int p,int l,int r) { if(l==r)return ; int mid=l+r>>1,x=l,y=mid+1; int nm=0,cnt=0; for(int i=mid;a[i]==a[mid];i--)nm++; for(int i=l;i<=r;i++) { if(t[p].s[i]<a[mid]) { t[p+1].s[x++]=t[p].s[i]; cnt++; t[p].c[i]=cnt; continue; } if(t[p].s[i]>a[mid]) { t[p+1].s[y++]=t[p].s[i]; t[p].c[i]=cnt; continue; } if(nm) { t[p+1].s[x++]=t[p].s[i]; cnt++; t[p].c[i]=cnt; nm--; } else { t[p+1].s[y++]=t[p].s[i]; t[p].c[i]=cnt; } } build(p+1,l,mid); build(p+1,mid+1,r); } int num(int l,int r,int k,int p,int b,int e) { if(l==r)return t[p].s[l]; int mid=b+e>>1,s,ss; if(l==b) {s=0;ss=t[p].c[r];} else{s=t[p].c[l-1];ss=t[p].c[r]-s;} if(k<=ss) { return num(b+s,b+s+ss-1,k,p+1,b,mid); } else { return num(mid+l-b-s+1,mid+r-ss-s-b+1,k-ss,p+1,mid+1,e); } } int main(){ int n,m; scanf("%d%d",&n,&m); int cnt=0; for(int i=1;i<=n;i++) { scanf("%d",&t[1].s[i]); a[++cnt]=t[1].s[i]; } sort(a+1,a+cnt+1); build(1,1,n); while(m--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); printf("%d\n",num(x,y,z,1,1,n)); } return 0; }
相关文章推荐
- noi 2010 超级钢琴 划分树
- poj 2104 K-th Number(划分树)
- 划分树详解 结合例题hdu4251
- poj2104——K-th Number(划分树)
- HDU 4417 Super Mario(划分树)
- HDU 4417 Super Mario (树状数组+离线处理)(划分树+二分答案)
- poj 2401 划分树 求区间第k大的数
- hdu 4417 划分树+二分
- BZOJ 2006 NOI2010 超级钢琴 划分树+堆
- 【HDU】4417 Super Mario(划分树+二分)
- Kth number(划分树)
- POJ 2104 K-th Number(区间第k大数)(平方分割,归并树,划分树)
- HDU 2665 Kth number 划分树 第一弹
- 归并树&划分树详解
- HDU 3473 Minimum Sum 划分树
- HDU 4417 Super Mario (划分树)(二分)
- POJ 题目2761 Feed the dogs(主席树||划分树)
- HDU - 2665 Kth number(划分树模板题)
- 求序列中第k大的元素(划分树模板)
- hdu 3473 Minimum Sum(划分树应用)