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_len,root[N],tot,x,y,pos,ic=1,k;
 7 struct node{int l,r,sum;}T[N*40];
 8
 9 inline int getid(int x){return lower_bound(hsh+1,hsh+1+hsh_len,x)-hsh;}
10 inline int getd(int x){return upper_bound(hsh+1,hsh+1+hsh_len,x)-hsh-1;}
11
12 void update(int &x,int y,int pos,int l=1,int r=n)
13 {
14     T[++tot]=T[y],T[tot].sum++,x=tot;
15     if(l==r)return;
16     int m=(l+r)>>1;
17     if(pos<=m)update(T[x].l,T[y].l,pos,l,m);
18     else update(T[x].r,T[y].r,pos,m+1,r);
19 }
20
21 int query(int x,int y,int pos,int l=1,int r=n)
22 {
23     if(l==r)return T[y].sum-T[x].sum;
24     int m=(l+r)>>1;
25     if(pos<=m)return query(T[x].l,T[y].l,pos,l,m);
26     else return T[T[y].l].sum-T[T[x].l].sum+query(T[x].r,T[y].r,pos,m+1,r);
27 }
28
29 int main()
30 {
31     scanf("%d",&t);
32     while(t--)
33     {
34         printf("Case %d:\n",ic++);
35         scanf("%d%d",&n,&m),tot=0;
36         F(i,1,n)scanf("%d",a+i),hsh[i]=a[i];
37         sort(hsh+1,hsh+1+n),hsh_len=unique(hsh+1,hsh+1+n)-hsh-1;
38         F(i,1,n)update(root[i],root[i-1],getid(a[i]));
39         F(i,1,m)scanf("%d%d%d",&x,&y,&pos),printf("%d\n",(k=getd(pos))==0?0:query(root[x],root[y+1],k));
40     }
41     return 0;
42 }

时间: 2024-10-25 19:24:54

hdu_4417_Super Mario(主席树)的相关文章

【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 主席树查询区间小于某个值的个数

#include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<vector> #define LL long long #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) #define pb push_back #d

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

[主席树]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(i

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,因为这个也错了几次.从师兄那里学习到了如果找一

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

主席树 | | 可持久化线段树

可持久化数据结构(Persistent data structure)就是利用函数式编程的思想使其支持询问历史版本.同时充分利用它们之间的共同数据来减少时间和空间消耗. 所以这里讲的可持久化线段树也叫函数式线段树(又叫主席树……因为先驱就是fotile主席Orz……). 先了解一下主席树 http://seter.is-programmer.com/posts/31907.html    很详细的介绍了函数式线段树(主席树). 主席树其实就是很多棵线段树,由于每次更新只需要更新logN个节点,所