hdu4417 Super Mario (树状数组/分块/主席树)
题目链接: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 (树状数组/分块/主席树)的更多相关文章
- 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 ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树
BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- P2617 Dynamic Rankings(树状数组套主席树)
P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...
- [COGS257]动态排名系统 树状数组套主席树
257. 动态排名系统 时间限制:5 s 内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】
题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...
随机推荐
- 20181022-JSP 开发环境搭建
JSP 开发环境搭建 JSP开发环境是您用来开发.测试和运行JSP程序的地方. 本节将会带您搭建JSP开发环境,具体包括以下几个步骤. 配置Java开发工具(JDK) 这一步涉及Java SDK的下载 ...
- [CSP-S模拟测试]:模板(ac)(线段树启发式合并)
题目描述 辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了.他每天都被$katarina$大神虐,仗着自己学过一些姿势就给$katarina$大神出了一道题.有一棵$n$个节点的以$1$号节 ...
- What does the dot after dollar sign mean in jQuery when declaring variables?
https://stackoverflow.com/questions/22156664/what-does-the-dot-after-dollar-sign-mean-in-jquery-when ...
- python 调用C++ DLL,传递int,char,char*,数组和多维数组
ctypes 数据类型和 C数据类型 对照表 ctypes type C type Python type c_bool _Bool bool (1) c_char char 1-character ...
- pc显示,手机隐藏
<div class="none"><img src="https://www.foresthouse.cn/bigpic.jpg"/> ...
- 职位-CTO:CTO
ylbtech-职位-CTO:CTO 首席技术官是技术资源的行政管理者,英文为Chief Technical Officer或Chief Technology Officer,简称CTO.其职责是制订 ...
- Node - 模块加载与 lerna 提升
从node_modules 加载模块的过程 如果要加载的模块非核心模块,并且路径不是'/'. '../'和'./'开头,这个模块就会从当前文件夹递归向上在node_modules文件夹中寻找这个模块. ...
- python-笔记(三)文件操作
文件的操作一般分三步: 1.打开文件,获取文件的指针(句柄) 2.通过指针(句柄)操作文件 3.关闭文件 现在有以下文件: 我们为爱还在学 学沟通的语言 学着谅解 学着不流泪 等到我们学会飞 飞越黑夜 ...
- 测开之路一百零三:jquery元素和标签的插入与删除
标签内插入 标签外插入 给标签加标签 !DOCTYPE html><html lang="en"><head> <meta charset=&q ...
- java通过HtmlUnit工具和J4L实现模拟带验证码登录
1.HtmlUnit 1.1介绍 HtmlUnit是一个用java编写的无界面浏览器,建模html文档,通过API调用页面,填充表单,点击链接等等.如同正常浏览器一样操作.典型应用于测试以及从网页抓取 ...