题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417

题目大意:给定一个长度为n的序列,有m个询问,每次询问包含l,r,h,即询问区间[l,r]小于等于h的数目。

解题思路:很多种解法,写了三种

1.树状数组离线处理

将序列和所有操作的h从小到大排序,都设为结构体类型以便保存下标,然后按顺序从小到大将序列的下标更新到树状数组中,如果下一个询问的h要大于当前询问的h时,则处理该询问,因为我们已经将小于等于h的数全部更新到树状数组中,所以直接区间求和即为答案。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
int sum[maxn];
int n,m;
struct node{
int h,id;
}p[maxn];
struct node1{
int l,r,h,id;
}q[maxn];
int ans[maxn];
bool cmp(node x,node y){
return x.h<y.h;
}
bool cmp1(node1 x,node1 y){
return x.h<y.h;
}
void update(int pos){
while(pos<=n){
sum[pos]++;
pos+=(pos&-pos);
}
}
int ask(int pos){
int res=;
while(pos){
res+=sum[pos];
pos-=(pos&-pos);
}
return res;
}
int main(){
int t;
scanf("%d",&t);
for(int tt=;tt<=t;tt++){
memset(sum,,sizeof(sum));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&p[i].h);
p[i].id=i;
}
for(int i=;i<=m;i++){
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);
q[i].l++; q[i].r++;
q[i].id=i;
}
sort(p+,p++n,cmp);
sort(q+,q++m,cmp1);
for(int i=,j=;j<=m;j++){
while(i<=n&&p[i].h<=q[j].h){ //将小于等于当前询问h的数的下标更新到树状数组中
update(p[i].id);
i++;
}
ans[q[j].id]=ask(q[j].r)-ask(q[j].l-); //查找该答案
}
printf("Case %d:\n",tt);
for(int i=;i<=m;i++){
printf("%d\n",ans[i]);
}
}
return ;
}

2.分块:

将n个序列分成根号n块,用两个数组同时存序列,a数组为原序列,b数组为每块进行排序后的序列。对于询问操作,如果询问区间只在某块的部分区间的直接暴力,对于整块都在询问区间的块可以采用二分。不过这种方法耗时多一点。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
int n,m,a[maxn],b[maxn],num,block,l[maxn],r[maxn],belong[maxn];
void build(){
block=sqrt(n);
num=n/block; if(n%block) num++;
for(int i=;i<=num;i++)
l[i]=(i-)*block+,r[i]=i*block;
r[num]=n;
for(int i=;i<=n;i++) belong[i]=(i-)/block+;
}
int ask(int x,int y,int val){
int res=;
if(belong[x]==belong[y]){
for(int i=x;i<=y;i++){
if(a[i]<=val) res++;
}
return res;
}
for(int i=x;i<=r[belong[x]];i++){
if(a[i]<=val) res++;
}
for(int i=l[belong[y]];i<=y;i++){
if(a[i]<=val) res++;
}
for(int i=belong[x]+;i<belong[y];i++){
int pos=upper_bound(b+l[i],b+r[i]+,val)-b-l[i];
res+=pos;
}
return res;
}
int main(){
int t;
scanf("%d",&t);
for(int tt=;tt<=t;tt++){
printf("Case %d:\n",tt);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
build();
for(int i=;i<=num;i++)
sort(b+l[i],b+r[i]+);
while(m--){
int x,y,h;
scanf("%d%d%d",&x,&y,&h);
x++; y++;
printf("%d\n",ask(x,y,h));
}
}
return ;
}

3.主席树

将主席树的板子的询问操作稍微改改就可以了,对于询问操作,直接先二分查找大于h的第一个编号x,然后查找第l颗线段树到第r颗线段树中小于x编号的和就可以了。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
struct node{
int l,r,sum;
}tree[maxn*];
int n,m,cnt,a[maxn],root[maxn];
vector<int> v;
int getid(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+;
}
void update(int l,int r,int &x,int y,int pos){
tree[++cnt]=tree[y],tree[cnt].sum++,x=cnt;
if(l==r) return;
int mid=(l+r)/;
if(pos<=mid) update(l,mid,tree[x].l,tree[y].l,pos);
else update(mid+,r,tree[x].r,tree[y].r,pos);
}
int query(int l,int r,int x,int y,int k){
if(l==r) return tree[y].sum-tree[x].sum;
int mid=(l+r)/,ans=;
if(k<=mid) ans+=query(l,mid,tree[x].l,tree[y].l,k);
else{
ans+=tree[tree[y].l].sum-tree[tree[x].l].sum;
ans+=query(mid+,r,tree[x].r,tree[y].r,k);
}
return ans;
}
int main(){
int T,tot=;
scanf("%d",&T);
while(T--){
v.clear();
scanf("%d%d",&n,&m);
for(int i=;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());
printf("Case %d:\n",++tot);
for(int i=;i<=n;i++) update(,n,root[i],root[i-],getid(a[i]));
while(m--){
int l,r,h;
scanf("%d%d%d",&l,&r,&h);
l++; r++;
int x=upper_bound(v.begin(),v.end(),h)-v.begin();
if(x==) printf("0\n");
else printf("%d\n",query(,n,root[l-],root[r],x));
}
}
return ;
}

hdu4417 Super Mario (树状数组/分块/主席树)的更多相关文章

  1. Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)

    E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...

  2. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  3. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  4. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  5. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  6. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  7. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

  8. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  9. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

随机推荐

  1. QT开发安卓APP的中文字体问题

    1.安卓默认的字体为DroidSansFallback:谷歌中文字体 由于手机和PC字体的不一致,导致PC上开发的APP到目的安卓设备中文显示为小方框. 故需要要在qt的main函数中设置系统字体: ...

  2. nginx修改默认运行80端口的方法

    修改方法 很简单,修改nginx的配置文件, 对应的值,如图: 将其改为别的端口号,就可以了.

  3. 如何在Ecplise调试之后恢复原来的界面

    在我们用Eclipse调试代码的时候,可以通过设置断点来调试,但是调试之后我们的界面会跟之前的不同,通过以下的方法可以让Eclipse的界面恢复成调试之前的样子. 在Ecplise中找到Window, ...

  4. 个推基于 Zipkin 的分布式链路追踪实践

    作者:个推应用平台基础架构高级研发工程师 阿飞   01业务背景   随着微服务架构的流行,系统变得越来越复杂,单体的系统被拆成很多个模块,各个模块通过轻量级的通信协议进行通讯,相互协作,共同实现系统 ...

  5. 在 mac 系统上安装 python 的 MySQLdb 模块

    在 mac 系统上安装 python 的 MySQLdb 模块 特别说明:本文主要参考了Mac系统怎么安装MySQLdb(MySQL-Python) 第 1 步:下载 MySQL-python-1.2 ...

  6. JavaSE知识点:finalize,treeMap

    *)finalize finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. *)treeMap 参考 ...

  7. C++ Primer 第四版阅读笔记

    阅读笔记 初始化 变量定义指定了变量的类型和标识符,也可以为对象提供初始值.定义时指定了初始值的对象被称为是 已初始化的.C++ 支持两种初始化变量的形式:复制初始化和 直接初始化.复制初始化语法用等 ...

  8. 记一次odoo创建新的模块时,但是在odoo web界面找不到应用的案例

    原因就是在odoo.conf配置文件中没有说明  模块查找的路径

  9. 使用spring配置类代替xml配置文件注册bean类

    spring配置类,即在类上加@Configuration注解,使用这种配置类来注册bean,效果与xml文件是完全一样的,只是创建springIOC容器的方式不同: //通过xml文件创建sprin ...

  10. python实现excel转换成pdf

    1.安装 需要安装pywin32包,以实现对Office文件的操作,可以批量转换为pdf文件.支持 doc, docx, ppt, pptx, xls, xlsx 等格式. pip install p ...