hdu--4417Super Mario+划分树

题目链接:点击进入

这道题就不能简单的套模板了,因为他是要判断给定的区间里有多少个值小于H。思路看完题后就有了,其实我们只要二分名次k,然后将得到的值与H进行比较就行了,这样就可以求出一个高度恰好小于H的名次作为答案了。但要注意一下,使用划分树求出的第k大值,其实是第k小值,开始就被被这一点坑了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=100000+100;
int tree[20][maxn];
int sorted[maxn];
int toleft[20][maxn];

bool cmp(int a,int b)
{
    return a>b;
}
void build(int l,int r,int dep)
{
    if(l==r) return;
    int mid=(l+r)>>1;
    int same=mid-l+1;
    for(int i=l;i<=r;i++)
       if(tree[dep][i]<sorted[mid])
          same--;
    int lpos=l;
    int rpos=mid+1;
    for(int i=l;i<=r;i++)
    {
        if(tree[dep][i]<sorted[mid])
           tree[dep+1][lpos++]=tree[dep][i];
        else if(tree[dep][i]==sorted[mid]&&same>0)
           tree[dep+1][lpos++]=tree[dep][i],same--;
        else
           tree[dep+1][rpos++]=tree[dep][i];
        toleft[dep][i]=toleft[dep][l-1]+lpos-l;
    }
    build(l,mid,dep+1);
    build(mid+1,r,dep+1);
}

int query(int L,int R,int l,int r,int dep,int k)
{
    if(l==r) return tree[dep][l];
    int mid=(L+R)/2;
    int cnt=toleft[dep][r]-toleft[dep][l-1];
    if(cnt>=k)
    {
        int newl=L+toleft[dep][l-1]-toleft[dep][L-1];
        int newr=newl+cnt-1;
        return query(L,mid,newl,newr,dep+1,k);
    }
    else
    {
        int newr=r+toleft[dep][R]-toleft[dep][r];
        int newl=newr-(r-l-cnt);
        return query(mid+1,R,newl,newr,dep+1,k-cnt);
    }
}
int main()
{
    freopen("in.txt","r",stdin);
    int t,Case=0;
    scanf("%d",&t);
    while(t--)
    {
        printf("Case %d:\n",++Case);
        int n,m;
        scanf("%d%d",&n,&m);
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&tree[0][i]);
            sorted[i]=tree[0][i];
        }
        sort(sorted+1,sorted+n+1);
        build(1,n,0);
        while(m--)
        {
            int L,R,H;
            scanf("%d%d%d",&L,&R,&H);
            L++,R++;
            int l=1,r=R-L+1;
            int ans=-1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                int tmp=query(1,n,L,R,0,mid);
                if(tmp<=H)
                  l=mid+1,ans=mid;
                else
                  r=mid-1;
            }
            if(ans==-1)
            {
                printf("0\n");
                continue;
            }
            printf("%d\n",ans);
        }
    }
  return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 06:05:20

hdu--4417Super Mario+划分树的相关文章

HDU-4417-Super Mario(划分树+二分)

Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss's castle as a l

HDU 4417 Super Mario 划分树/树状数组

题目大意:给定一个序列,求区间内小于等于某数的元素数量 首先区间排名一看就是划分树 不过和第k小不一样 我们需要做一些处理 第一种处理方式是二分答案 然后转换成区间第k小 好方法我喜欢 但是这里说的不是这种方法 首先建树,然后对于每个询问,我们讨论k与a[mid]的关系 若k<a[mid],则右子树一定没有小于等于k的数,我们进入左子树查找 若k>=a[mid],则左子树内一定所有数都小于等于k,于是我们将查询区间中进入左子树的元素的数量记入ans,然后查找右区间 递归退出条件是查询区间为空或

HDU 3473-Minimum Sum(划分树-求区间sigma最小值)

Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3710    Accepted Submission(s): 852 Problem Description You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you

HDU 4417 Super Mario(划分树问题求不大于k的数有多少)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3625    Accepted Submission(s): 1660 Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability

hdu 3473 (划分树)2

Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4611    Accepted Submission(s): 1046 Problem Description You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you

HDU 4417 Super Mario ( 超级马里奥 + 主席树 + 线段树/树状数组离线处理 + 划分树 )

HDU 4417 - Super Mario ( 主席树 + 线段树/树状数组离线处理 + 划分树 ) 这道题有很多种做法,我先学习的是主席树.后面陆续补上线段树离线和划分树 题目大意就是给定一个区间给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 主席树做法: 最基本的是静态第k大,这里是求静态的 <= K,差不多,在Query操作里面需要修改修改 先建立size棵主席树,然后询问的时候统计的是 第R棵主席树中[1,K]的数量 - 第L-1棵主席树中[1,K]的数量 注意这里下标

hdu 4417 Super Mario(离线树状数组|划分树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2584    Accepted Submission(s): 1252 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping a

HDU 4417 Super Mario (划分树)(二分)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6077    Accepted Submission(s): 2645 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ab

【划分树+二分】HDU 4417 Super Mario

第一次 耍划分树.. . 模板是找第k小的 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <queue> #include &l