HDU4417 Super Mario(离线树状数组或者主席树+二分)

2023-11-10 00:00

本文主要是介绍HDU4417 Super Mario(离线树状数组或者主席树+二分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Super Mario

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10963    Accepted Submission(s): 4580


 

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 line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.

 

 

Input

The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)

 

 

Output

For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.

 

 

Sample Input

 

1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3

 

 

Sample Output

 

Case 1: 4 0 0 3 1 2 0 1 5 1

 

 

Source

2012 ACM/ICPC Asia Regional Hangzhou Online

 

题意:

给你一个数组,多次询问,每一次询问区间里[l,r],有多少个数<=h?

分析:

离线树状数组

我们分别对操作排序,按照h的大小排序,对于最小的h来说,将<=h的数按下标加入到树状数组当中,则sum(r)-sum(l-1)就为答案。这题的核心就是在进行询问时,只有小于等于h的数在树状数组当中。

主席树+二分

主席数可以查出区间第k小的元素,我们二分这个k,找到第k小的元素<=h的最大的那一个即可。

离线树状数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 11;
const int mod =  1e9 + 7;
//树状数组只能计算A[1]开始的和,A[0]这个元素是不能用的。
const int MAXN=100000+5;//最大元素个数
int n,m;//元素个数
int c[MAXN];//c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1]
//返回i的二进制最右边1的值
int lowbit(int i)
{return i&(-i);
}
//返回A[1]+...A[i]的和
ll sum(int x)
{ll sum = 0;while(x){sum += c[x];x -= lowbit(x);}return sum;
}//令A[i] += val
void add(int x, ll val)
{while(x <= n)   //注意这里的n,是树状数组维护的长度{c[x] += val;x += lowbit(x);}
}
struct Node
{int val;int index;
} a[N];
bool cmp1(Node x,Node y)
{return x.val<y.val;
}
struct Option
{int l,r,w;int index;
} op[N];
bool cmp2(Option x,Option y)
{return x.w<y.w;
}
int ans[N];
int main()
{int T;scanf("%d",&T);int kase=0;while(T--){kase++;memset(c,0,sizeof(c));scanf("%d%d",&n,&m);for(int i=1; i<=n; i++){scanf("%d",&a[i].val);a[i].index=i;}sort(a+1,a+n+1,cmp1);for(int i=1; i<=m; i++){scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].w);op[i].l++;op[i].r++;op[i].index=i;}sort(op+1,op+m+1,cmp2);int top=1;for(int i=1; i<=m; i++){while(top<=n&&a[top].val<=op[i].w){add(a[top].index,1);top++;}ans[op[i].index]=sum(op[i].r)-sum(op[i].l-1);}printf("Case %d:\n",kase);for(int i=1;i<=m;i++){printf("%d\n",ans[i]);}}return 0;
}

主席树+二分

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll ;
const int oo=0x7f7f7f7f ;
const int maxn=1e5+7;
const int mod=1e9+7;
int t,n,m,cnt,root[maxn],a[maxn];
//cnt和root:主席树的总点数和每一个根
struct node
{int l,r,sum;
} T[maxn*25];
vector<int> v;
int getid(int x)  //离散化
{return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
///单点修改
void update(int l,int r,int &x,int y,int pos)
{T[++cnt]=T[y],T[cnt].sum++,x=cnt;if(l==r)return;int mid=(l+r)/2;if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos);elseupdate(mid+1,r,T[x].r,T[y].r,pos);
}
///查询区间(x,y)第k小
int query(int l,int r,int x,int y,int k)
{if(l==r)return l;int mid=(l+r)/2;int sum=T[T[y].l].sum-T[T[x].l].sum;if(sum>=k)return query(l,mid,T[x].l,T[y].l,k);elsereturn query(mid+1,r,T[x].r,T[y].r,k-sum);
}
int two_find(int x,int y,int k)
{int l=0,r=y-x+1;while(l<r){int mid=(l+r+1)>>1;if(v[query(1,n,root[x-1],root[y],mid)-1]<=k)l=mid;elser=mid-1;}return l;}
int main(void)
{scanf("%d",&t);int kase=0;while(t--){v.clear();cnt=0;kase++;scanf("%d%d",&n,&m);for(int i=1; i<=n; i++){scanf("%d",&a[i]);v.push_back(a[i]);}sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());for(int i=1; i<=n; i++)update(1,n,root[i],root[i-1],getid(a[i]));printf("Case %d:\n",kase);for(int i=1; i<=m; i++){int x,y,k;scanf("%d%d%d",&x,&y,&k);x++,y++;printf("%d\n",two_find(x,y,k));}}return 0 ;
}

 

 

这篇关于HDU4417 Super Mario(离线树状数组或者主席树+二分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/379232

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj 3104 二分答案

题意: n件湿度为num的衣服,每秒钟自己可以蒸发掉1个湿度。 然而如果使用了暖炉,每秒可以烧掉k个湿度,但不计算蒸发了。 现在问这么多的衣服,怎么烧事件最短。 解析: 二分答案咯。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <c

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 2594 二分图最大独立集

题意: 求一张图的最大独立集,这题不同的地方在于,间接相邻的点也可以有一条边,所以用floyd来把间接相邻的边也连起来。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <sta