您的位置:首页 > 理论基础 > 计算机网络

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  query build struct 网络 c