[主席树]HDOJ4417 Super Mario

题意:n个数 m个询问  ($n、m \le 10^5$)

每个询问有l, r, k  问的是[l, r]区间内有多少个数小于等于k

用主席树做的话查询第i小的数与k比较即可

  1 #define lson l, m
  2 #define rson m+1, r
  3 const int N=1e5+5;
  4 int L[N<<5], R[N<<5], sum[N<<5];
  5 int tot;
  6 int a[N], T[N], Hash[N];
  7 int build(int l, int r)
  8 {
  9     int rt=(++tot);
 10     sum[rt]=0;
 11     if(l<r)
 12     {
 13         int m=(l+r)>>1;
 14         L[rt]=build(lson);
 15         R[rt]=build(rson);
 16     }
 17     return rt;
 18 }
 19
 20 int update(int pre, int l, int r, int x)
 21 {
 22     int rt=(++tot);
 23     L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+1;
 24     if(l<r)
 25     {
 26         int m=(l+r)>>1;
 27         if(x<=m)
 28             L[rt]=update(L[pre], lson, x);
 29         else
 30             R[rt]=update(R[pre], rson, x);
 31     }
 32     return rt;
 33 }
 34
 35 int query(int u, int v, int l, int r, int k)
 36 {
 37     if(l>=r)
 38         return l;
 39     int m=(l+r)>>1;
 40     int num=sum[L[v]]-sum[L[u]];
 41     if(num>=k)
 42         return query(L[u], L[v], lson, k);
 43     else
 44         return query(R[u], R[v], rson, k-num);
 45 }
 46
 47 int main()
 48 {
 49     int t, ca=1;
 50     scanf("%d", &t);
 51     while(t--)
 52     {
 53         tot=0;
 54         int n, m;
 55         scanf("%d%d", &n, &m);
 56         for(int i=1; i<=n; i++)
 57         {
 58             scanf("%d", &a[i]);
 59             Hash[i]=a[i];
 60         }
 61         sort(Hash+1, Hash+n+1);
 62         int d=unique(Hash+1, Hash+n+1)-Hash-1;
 63         T[0]=build(1, d);
 64         for(int i=1; i<=n; i++)
 65         {
 66             int x=lower_bound(Hash+1, Hash+d+1, a[i])-Hash;
 67             T[i]=update(T[i-1], 1, d, x);
 68         }
 69         printf("Case %d:\n", ca++);
 70         while(m--)
 71         {
 72             int l, r, k;
 73             scanf("%d%d%d", &l, &r, &k);
 74             l++, r++;
 75             int ll=1, rr=r-l+1;
 76             int ans=0;
 77             while(ll<=rr)
 78             {
 79                 int mm=(ll+rr)>>1;
 80                 int tmp=Hash[query(T[l-1], T[r], 1, d, mm)];
 81                 if(tmp<=k)
 82                 {
 83                     if(mm==r-l+1 || Hash[query(T[l-1], T[r], 1, d, mm+1)]>k)
 84                     {
 85                         ans=mm;
 86                         break;
 87                     }
 88                     ll=mm+1;
 89                 }
 90                 else
 91                 {
 92                     if(mm==1 || Hash[query(T[l-1], T[r], 1, d, mm-1)]<=k)
 93                     {
 94                         ans=mm-1;
 95                         break;
 96                     }
 97                     rr=mm-1;
 98                 }
 99             }
100             printf("%d\n", ans);
101         }
102     }
103     return 0;
104 }

HDOJ 4417

时间: 2024-10-06 01:28:46

[主席树]HDOJ4417 Super Mario的相关文章

HDOJ 4417 Super Mario

划分树+二分 Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2625    Accepted Submission(s): 1274 Problem Description Mario is world-famous plumber. His "burly" figure and amazing ju

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): 5101    Accepted Submission(s): 2339 Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping abilit

HDU 4417:Super Mario(主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意是:给出n个数和q个询问,每个询问有一个l,r,h,问在[l,r]这个区间里面有多少个数是小于等于h的. 思路:比较裸的主席树,注意题意给的区间是从[0,n-1],一开始看错导致想错了很多东西.询问的时候如果m < h,那么左子树全部都是小于 h 的,就加上左子树的 sum,继续查右子树,否则就查左子树.最后 l == r 的时候要判下 h >= l,因为这个也错了几次.从师兄那里学习到了如果找一

【hdu4417】Super Mario——主席树

题目链接 题目大意为给定一个长度为n的区间,同时给出m个询问,每次询问在区间[l,r]中有多少个数小于或等于k. 同样考虑用主席树来维护,每次只需要找到序列b中第一个等于k的数,那么要求的数必定在b[1]~b[upper_bound(k)]这个范围内,接下来就像线段树统计区间个数那样,若完全包含则直接加上e[rr].sum-e[ll].sum,否则就分两边递归统计.而建树什么的就直接套模板即可. 还要注意一点,原题的区间默认从0开始,因此若像我一样写了区间从1开始的记得在query之前将l和r加

hdu 4417 Super Mario(主席树)

题意:给你一些数,有多次询问,问你在l,r区间内小于k的数有多少个 思路:主席树大发好,虽然树状数组和线段树离线也可以做 代码: #include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <vector> #include <string> #include <stdio.h> #incl

hdu 4417 Super Mario (主席树)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意: 给你段长为n的序列,有q个询问,每次询问区间[l.r]内有多少个数小于等于k 思路: 之前用分块写过类似的,不过为了练习下主席树,这里用主席树写了下.思路很简单 离线离散化处理下,每次插入一个数num时,在主席树上下标num+1,这样每次询问[l,r]中有多少个小于k的数的时候,我们只要找下标[1,k]的区间第R次修改后的总和减去第L-1次修改后的总值就可以得到了 实现代码: #inclu

hdu-4417 Super Mario(树状数组 + 划分树)

题目链接: Super Mario Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is

hdu_4417_Super Mario(主席树)

题目链接:hdu_4417_Super Mario 题意: 给你n个树,有m个询问,每个询问有一个区间和一个k,问你这个区间内不大于k的数有多少个. 题解: 考虑用主席树的话就比较裸,当然也可以用其他的写 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 5 const int N=1e5+7; 6 int a[N],t,n,m,hsh[N],hsh_le