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次修改后的总值就可以得到了

实现代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int M = 2e5+10;
int ls[M*40],rs[M*40],sum[M*40],a[M],b[M],root[M];
int idx;
void build(int &k,int l,int r){
    k = ++idx;
    sum[k] = 0;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    build(ls[k],l,mid); build(rs[k],mid+1,r);
}

void update(int old,int &k,int l,int r,int p,int c){
    k = ++idx;
    ls[k] = ls[old]; rs[k] = rs[old];
    sum[k] = sum[old] + c;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    if(p <= mid) update(ls[old],ls[k],l,mid,p,c);
    else update(rs[old],rs[k],mid+1,r,p,c);
}

int query(int old,int k,int L,int R,int l,int r){
    if(L <= l&&R >= r) return sum[k] - sum[old];
    int mid = (l + r) >> 1;
    int ret = 0;
    if(L <= mid) ret += query(ls[old],ls[k],L,R,l,mid);
    if(R > mid) ret += query(rs[old],rs[k],L,R,mid+1,r);
    return ret;
}
int l[M],r[M],x[M],cnt;
int Find(int x){
    int num = lower_bound(b+1,b+1+cnt,x)-b;
    return num;
}

int main()
{
    int t,q,n,cas=1;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        for(int i = 1;i <= n;i ++)
            scanf("%d",&a[i]),b[i] = a[i];
        for(int i = 1;i <= q;i ++)
            scanf("%d%d%d",&l[i],&r[i],&x[i]),b[i+n]=x[i];
        sort(b+1,b+1+n+q);
        cnt = unique(b+1,b+1+n+q)-b-1;
        for(int i = 1;i <= n;i++){
            int fx = Find(a[i]);
            update(root[i-1],root[i],1,cnt,fx,1);
        }
        printf("Case %d:\n",cas++);
        for(int i = 1;i <= q;i ++){
            int fx = Find(x[i]);
            printf("%d\n",query(root[l[i]],root[r[i]+1],1,fx,1,cnt));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kls123/p/9568553.html

时间: 2024-10-06 18:56:58

hdu 4417 Super Mario (主席树)的相关文章

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(离线树状数组|划分树)

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(划分树问题求不大于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 4417 Super Mario 划分树/树状数组

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

hdu 4417 Super Mario (线段树+离线)

题意: n个砖块,第i个砖块的高度是hi. m个query,每个query的格式:L R H (输出[L,R]中有多少个hi小于等于H[即玛里奥能跳过多少块砖]) 数据范围: 1 <= n <=10^5, 1 <= m <= 10^5 Next line contains n integers, the height of each brick, the range is [0, 1000000000]. ( 0 <= L <= R < n 0 <= H &

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(主席树)

题意:给你一些数,有多次询问,问你在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 (树状数组/线段树)

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