HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)
题意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 作差的绝对值的第 k 小,这个绝对值是多少
分析:首先我们先分析单次查询怎么做:
题目给出的数据与多次查询已经在提示着我们在用数据结构去解决这个问题,对于常见的处理区间的数据结构首选线段树啦:
我觉得这道题的关键在于此:我们需要去二分答案ans, 为什么呢? 我们这样观察 ,对于 | p-a[i] | <= ans 等于 p-ans<=a[i] <=p+ans 那问题就转化为查询[L,R] 区间里面在[p-ans,p+ans] 范围的a[i] 有多少个 。这显然是到主席树的题目;
我们明白主席树的原理是多颗权值线段树 , 那我们就把a[i]当成下标,权值为出现的次数,那我们就是查询[L,R] 编号是权值线段树里面[p-ans,p+ans] 范围的a[i] 有多少个 。
主席树:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+;
int tot;
int lson[N],rson[N],sum[N],tr[N];
void build(int &rt,int l,int r){
rt=++tot;
if(l==r) return ;
int mid=(l+r)>>;
build(lson[rt],l,mid);
build(rson[rt],mid+,r);
}
void updata(int root,int &rt,int p,int l,int r){
rt=++tot;
lson[rt]=lson[root],rson[rt]=rson[root];
sum[rt]=sum[root]+;
if(l==r) return ;
int mid=(l+r)>>;
if(p<=mid) updata(lson[root],lson[rt],p,l,mid);
else updata(rson[root],rson[rt],p,mid+,r);
}
int query(int rt_,int rt,int L,int R,int l,int r){
if(l<=L&&R<=r){
return sum[rt_]-sum[rt];
}
int mid=(L+R)>>;
int ans=;
if(l<=mid)
ans+=query(lson[rt_],lson[rt],L,mid,l,r);
if(mid<r)
ans+=query(rson[rt_],rson[rt],mid+,R,l,r);
return ans;
}
int main(){
int _;scanf("%d",&_);
while(_--){
int n,m;scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
int x;scanf("%d",&x);
updata(tr[i-],tr[i],x,,N);
}
int T=;
for(int i=;i<=m;i++){
int L,R,p,k; scanf("%d%d%d%d",&L,&R,&p,&k);
L^=T,R^=T,p^=T,k^=T;
int LL=,RR=1e6,ans=;
while(LL<=RR){
int mid=(LL+RR)>>;
int l=max(,p-mid);
int r=min(N,p+mid);
if(query(tr[R],tr[L-],,N,l,r)>=k){
RR=mid-;ans=mid;
}
else LL=mid+;
}
T=ans;
printf("%d\n",ans);
} }
return ;
}
权值线段树的做法:
要解决的问题依然没有变;
线段树的每个节点都存着对应区间有序的序列,比如{5,1,2,3,4} ,对于这样的一个序列,线段树的根节点表示的是区间[1,5] 节点里面存有序列{1,2,3,4,5} 那我们查询p-ans<=a[i] <=p+ans ,就二分{1,2,3,4,5}这个有序的序列有多少个大于p+ans,多少个
大于p-ans-1,在相减;这钟线段树,真的是前所未闻........
#include<bits/stdc++.h> using namespace std;
const int N=1e5+;
vector<int>v[N];
vector<int>::iterator it;
int a[N];
void build(int l,int r,int rt){
v[rt].clear();
for(int i=l;i<=r;i++)
v[rt].push_back(a[i]);
sort(v[rt].begin(),v[rt].end());
if(l==r) return ;
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
}
int query(int L,int R,int rt,int l,int r,int val){
if(l<=L&&R<=r){
it=upper_bound(v[rt].begin(),v[rt].end(),val);
return it-v[rt].begin();
}
int ans=;
int mid=(L+R)>>;
if(l<=mid)
ans+=query(L,mid,rt<<,l,r,val);
if(mid<r)
ans+=query(mid+,R,rt<<|,l,r,val);
return ans;
}
int main(){
int _; scanf("%d",&_);
while(_--){
int n,m; scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
build(,n,);
int L1=,R1=,p1=,k1=;
int T=;
for(int i=;i<=m;i++){
int L,R,p,k;
scanf("%d%d%d%d",&L,&R,&p,&k);
L^=T,R^=T,p^=T,k^=T;
int LL=,RR=1e6,ans=;
while(LL<=RR){
int mid=(LL+RR)>>;
int K=query(,n,,L,R,p+mid)-query(,n,,L,R,p-mid-);
if(K>=k) {RR=mid-;ans=mid;}
else LL=mid+;
}
printf("%d\n",ans);
T=ans;
}
}
return ;
}
HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)的更多相关文章
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树
经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
- 动态求区间K大值(权值线段树)
我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...
- BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- 区间第k大问题 权值线段树 hdu 5249
先说下权值线段树的概念吧 权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树 用这个加权线段树 解决第k大问题就很方便了 int query(int l,int r,int rt,int k ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
随机推荐
- RBAC----基于角色的访问权限控制
RBAC是什么? 基于角色的权限访问控制(Role-Based Access Control) 作为传统访问控制(自主访问.强制访问)的有前景的代替 受到了广泛的关注. 在RBAC中,权限与角色相关联 ...
- 全自动网络安装centos(一)安装前准备工作
centos系统启动文件详解: 注:在centos6里需要给NetworkManager服务关闭并且禁止开机启动,6和7里都需要将selinux关闭,否则会出现网络配置异常情况,并且要将防火墙关闭. ...
- shell学习笔记3---shell变量
Shell变量的定义.赋值和删除 脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则. 在 Bash shell 中,每一个变量的值都是字符串,无论你给变量赋值时有 ...
- Python 入门之Python基础知识
Python 入门之Python基础知识 1.变量 (1)变量就是把程序运行的中间结果临时存在内存中,以便后续代码使用 (2)变量的作用: 昵称,就是代指内存中某个地址中的内容 a = 123 变量名 ...
- Restful风格API中用put还是post做新增操作有什么区别?
Restful风格API中用put还是post做新增操作有什么区别? 转 头条面试归来,有些话想和Java开发者说!>>> 这个是华为面试官问我的问题,回来我找了很多资料,想验证这个 ...
- “百度杯”CTF比赛 十一月场--CrackMe01
测试文件:https://static2.ichunqiu.com/icq/resources/fileupload/CTF/BSRC/BSRC-11-3/CrackMe01_97D2BF0DBD2E ...
- JCTF 2014 小菜两碟
测试文件:https://static2.ichunqiu.com/icq/resources/fileupload//CTF/JCTF2014/re200 参考文章:https://blog.csd ...
- Scala学习笔记(6)对象
1.单例对象.Scala没有静态方法或字段,可以使用object这个语法结构来达到同样的目的.对象定义了单个实例,包含了你想要的特性. object Accounts{ def newUniqueNu ...
- 方法签名_spring aop_around
//注解签名 方法签名 Signature signature = pjp.getSignature(); MethodSignature methodSignature= (MethodSignat ...
- 奇葩的狐火浏览器border属性
今天接到一个bug任务,客户反映火狐浏览器访问时某个商品楼层不显示商品.我立即打开我的火狐浏览器发现没有复现这个bug,后来经过一番折腾,才发现火狐浏览器缩放到90%时,商品楼层果然就消失了,而且每台 ...