hdu 4417 Super Mario--二分--划分树
2012-10-02 15:17
363 查看
/* 2012年杭州网络赛的题目 就是求一个区间内<=某数 的个数 我是用的二分划分树的方法做的 */ #include<iostream> #include<algorithm> #include<stdio.h> using namespace std; const int N=100010; int srted ; struct node { int num ; int val ; }t[40]; int n,m; void build(int l,int r,int d)//建树 此树并非由节点构成 而是由数组的一段构成 如:d层的l~r是一个节点 { if(l==r) return; int mid=(l+r)>>1;//取中间那个 int midd=srted[mid]; int same=mid-l+1,samed=0,zn=l-1,yn=mid,i;//same初识化为左孩子元素个数 //下面减去比midd小的(一定会进入左孩子里边) 剩下的就是==midd并且要进入左孩子的个数 //samed是已经插入的数目 //zn、yn是左右孩子的开始位置-1,下面会把元素分到两个孩子的区域里边 for(i=l;i<=r;++i) if(t[d].val[i]<midd) --same; for(i=l;i<=r;++i)//有点像快排 大的放到后边 小的放前边 相等的看情况 { if(i==l) t[d].num[i]=0; else t[d].num[i]=t[d].num[i-1]; if(t[d].val[i]<midd) { ++t[d].num[i];//这里是统计从l到i有多少元素进入了左孩子 这是划分树主要用到的数据 t[d+1].val[++zn]=t[d].val[i]; }else if(t[d].val[i]>midd)//进入右孩子 { t[d+1].val[++yn]=t[d].val[i]; }else { if(samed<same)//名额还没有用完 放左孩子里边 { ++samed; ++t[d].num[i]; t[d+1].val[++zn]=t[d].val[i]; }else//方有孩子里边 t[d+1].val[++yn]=t[d].val[i]; } } build(l,mid,d+1);//建左右子树 build(mid+1,r,d+1); } int query(int a,int b,int k,int l,int r,int d)//在d层[l,r]的节点里查找[a,b]中的第k大值 { if(a==b) return t[d].val[a]; int mid=(l+r)>>1; int sx=t[d].num[a-1],sy=t[d].num[b]; if(a-1<l) sx=0; if(sy-sx>=k)//[a,b]进入左子树的元素>=k return query(l+sx,l+sy-1,k,l,mid,d+1); else { int s1=(a==1?0:a-l-sx); int s2=(b-a+1)-(sy-sx); int nk=k-(sy-sx);//前(sy-sx)大的元素在左子树里 剩下的在右子树里边找 return query(mid+1+s1,mid+s1+s2,nk,mid+1,r,d+1); } } int solve(int n,int s,int t,int h) { int ans=0; int l=1; int r=(t-s)+1; int mid; while(l<=r) { mid=(l+r)>>1; int temp=query(s,t,mid,1,n,0); if(temp<=h) { ans=mid; l=mid+1; } else r=mid-1; } return ans; } int main() { // freopen("in.txt","r",stdin); int tt,ti,i; int a,b,c,ret; int min,max,mid; scanf("%d",&tt); for(ti=1;ti<=tt;ti++) { cout<<"Case "<<ti<<":\n"; scanf("%d%d",&n,&m); for(i=1;i<=n;++i) { scanf("%d",&srted[i]); t[0].val[i]=srted[i]; } sort(srted+1,srted+1+n); build(1,n,0); for(i=1;i<=m;++i) { scanf("%d%d%d",&a,&b,&c); a++,b++; if(a==b) { if(t[0].val[a]<=c) cout<<"1"<<endl; else cout<<"0"<<endl; continue; } cout<<solve(n,a,b,c)<<endl; } } return 0; }
相关文章推荐
- HDU 4417-Super Mario(划分树-二分查找)
- 【划分树+二分】HDU 4417 Super Mario
- HDU 4417 Super Mario 划分树 + 二分
- 【划分树+二分】HDU 4417 Super Mario
- 【划分树+二分】HDU 4417 Super Mario
- 【HDU】4417 Super Mario(划分树+二分)
- HDU 4417 Super Mario(划分树+二分)
- hdu 4417 Super Mario 划分树+二分
- HDU-4417-Super Mario(划分树+二分)
- hdu 4417 Super Mario (二分法 + 划分树求区间第K大)
- HDU 4417 Super Mario (树状数组+离线处理)(划分树+二分答案)
- HDU 4417 Super Mario(划分树+二分)
- HDU 4417 Super Mario(划分树+二分)
- HDU 4417 Super Mario(划分树问题求不大于k的数有多少)
- HDU 4417 Super Mario(12年杭州 离线线段树||在线划分树)
- hdu 4417 划分树加二分 求区间内小于num的数的个数
- HDOJ题目4417 Super Mario(划分树求区间比k小的个数+二分)
- HDU 4417 - Super Mario (求区间小于h的数 划分树 二分 线段树 树状数组)
- HDU 4417 Super Mario--离线树状数组、划分树、线段树
- HDOJ题目4417 Super Mario(划分树求区间比k小的个数+二分)