POJ-2104-K-th Number

近几天都在做线段树的题,看到这个题本来想从线段树着手。结果发现这个题用划分树做,看了下资料和别人的博客~

地址:http://shizhixinghuo.diandian.com/post/2012-09-02/40037691896

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+200;
int n,m,sorted[maxn],t[25][maxn],toleft[25][maxn];
void Build(int l,int r,int deep)
{
    if(l==r)
	return;
    int mid=(l+r)>>1;
    int same=mid-l+1;
    for(int i=l;i<=r;i++)
	if(t[deep][i]<sorted[mid])
	    same--;
    int ls=l,rs=mid+1;
    for(int i=l;i<=r;i++)
    {
	toleft[deep][i]=toleft[deep][i-1];
	if(t[deep][i]<sorted[mid])
	{
	    t[deep+1][ls++]=t[deep][i];
	    toleft[deep][i]++;
	}
	else if(t[deep][i]==sorted[mid])
	{
	    if(same)
	    {
		t[deep+1][ls++]=t[deep][i];
		toleft[deep][i]++;
		same--;
	    }
	    else
		t[deep+1][rs++]=t[deep][i];
	}
	else
	    t[deep+1][rs++]=t[deep][i];
    }
    Build(l,mid,deep+1);
    Build(mid+1,r,deep+1);
}
int Query(int l,int r,int L,int R,int k,int deep)
{
    if(l==r)
	return t[deep][l];
    int mid=(L+R)>>1;
    int x=toleft[deep][l-1]-toleft[deep][L-1];	
    int y=toleft[deep][r]-toleft[deep][L-1];
    int ry=r-L-y;
    int rx=l-L-x;
    int cnt=y-x;
    if(cnt>=k)
	return Query(L+x,L+y-1,L,mid,k,deep+1);
    else
	return Query(mid+rx+1,mid+1+ry,mid+1,R,k-cnt,deep+1);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
	for(int i=1;i<=n;i++)
	{
	    scanf("%d",&sorted[i]);
	    t[0][i]=sorted[i];
	}
	sort(sorted+1,sorted+n+1);
	Build(1,n,0);
	while(m--)
	{
	    int a,b,k;
	    scanf("%d%d%d",&a,&b,&k);
	    printf("%d\n",Query(a,b,1,n,k,0));
	}
    }
    return 0;
}


你可能感兴趣的:(划分树)