码迷,mamicode.com
首页 > 其他好文 > 详细

hdu4417(划分树)--二分

时间:2015-05-31 00:09:53      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <queue>         //hdu4417(划分树)--二分
#define N 100010
using namespace std;
int sorted[N], p[20][N], num[20][N];
void build(int l, int r, int n)
{
    if(l==r)return ;
    int t, count, lr=l, mid, rh;
    mid=(l+r)>>1;
    rh=mid+1;
    for(t=mid, count=0; t>=l; --t)
    {
        if(sorted[mid]==sorted[t])
            count++;
        else break;
    }
    for(t=l; t<=r; ++t)
    {
        num[n][t]=num[n][t-1];
        if(p[n][t]==sorted[mid])
        {
            if(count)
            {
                count--;
                p[n+1][lr++]=p[n][t];
                num[n][t]++;
            }
            else 
            {
                p[n+1][rh++]=p[n][t];
            }
        }
        else if(p[n][t]<sorted[mid])
        {
            p[n+1][lr++]=p[n][t];
            num[n][t]++;
        }
        else p[n+1][rh++]=p[n][t];
    }
    build(l, mid, n+1);
    build(mid+1, r, n+1);
    return ;
}
int query(int n, int l, int r, int ql, int qr, int k)  //求在[ql,qr]内第k小的数
{
	if(l==r)return p[n][l];
    int s=0, s1, s2, s3, mid;  
    mid=(l+r)>>1;
	s1=num[n][qr]-num[n][ql-1];   //[ql,qr]左孩子的个数
	s2=num[n][ql-1]-num[n][l-1];  //[l,ql)左孩子的个数
	if(k<=s1)
	{
		return query(n+1, l, mid, l+s2, l+s1+s2-1, k);
	}
	else 
	{
		s2=ql-l-s2; //[l,ql)右孩子的个数
		s3=qr-ql+1-s1;  //[ql,qr]右孩子的个数
		return query(n+1, mid+1, r, mid+1+s2, mid+s2+s3, k-s1);
	}
}
int solve(int a, int b, int c, int n)  //二分
{
	int l=1, r=b-a+1, mid, ans=0, k;  //r是这个区间的长度,二分是按在这个区间(a,b)内第几小(名次)来二分的
	while(l<=r)
	{
		mid=(l+r)>>1;
		k=query(0, 1, n, a, b, mid);  //k第几小的数
		if(c>=k) //名次要更后 
		{
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	return ans;
}
int main()
{
    int n, m, t, T, i, l, r, h;
    scanf("%d", &T);
    for(i=1; i<=T; ++i)
    {
        scanf("%d%d", &n, &m);
        for(t=1; t<=n; ++t)
        {
            scanf("%d", sorted+t);
            p[0][t]=sorted[t];
        }
        sort(sorted+1, sorted+n+1);
        build(1, n, 0);
		printf("Case %d:\n", i);
        for(t=0; t<m; ++t)
        {
            scanf("%d%d%d", &l, &r, &h);
            l++;
            r++;
			printf("%d\n", solve(l, r, h, n));
        }
    }
    return 0;
}

hdu4417(划分树)--二分

标签:

原文地址:http://blog.csdn.net/u012432475/article/details/16355455

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!