题意:给一个数组,每次给 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 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)的更多相关文章

  1. 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树

    题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...

  2. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  3. 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树

    经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...

  4. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

  5. 动态求区间K大值(权值线段树)

    我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...

  6. BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...

  7. 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...

  8. 区间第k大问题 权值线段树 hdu 5249

    先说下权值线段树的概念吧 权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树 用这个加权线段树 解决第k大问题就很方便了 int query(int l,int r,int rt,int k ...

  9. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

随机推荐

  1. [BZOJ 3771] Triple(FFT+容斥原理+生成函数)

    [BZOJ 3771] Triple(FFT+生成函数) 题面 给出 n个物品,价值为别为\(w_i\)且各不相同,现在可以取1个.2个或3个,问每种价值和有几种情况? 分析 这种计数问题容易想到生成 ...

  2. 使用redis+flask维护动态代理池

    在进行网络爬虫时,会经常有封ip的现象.可以使用代理池来进行代理ip的处理. 代理池的要求:多站抓取,异步检测.定时筛选,持续更新.提供接口,易于提取. 代理池架构:获取器,过滤器,代理队列,定时检测 ...

  3. PCIeのType0与Type1型配置请求与BAR(基地址寄存器)

    PCIe中存在两种配置空间Type0&type1,TYPE0对应非桥设备(Endpoint),Type1对应桥设备(Root和Switch端口中的P2P桥)因为Root每个端口总都含有一个P2 ...

  4. scala学习笔记(9)

    一.高阶函数 --------------------------------------------------- 1.作为值的函数:在Scala中,函数是头等公民,就和数字一样. import s ...

  5. rabitMQ-centos7安装

    1.安装rabitMq之前需要安装Erlang cd /usr/local/ wget http://erlang.org/download/otp_src_18.3.tar.gz tar -zxvf ...

  6. java调用webservice接口 几种方法

    webservice的 发布一般都是使用WSDL(web service descriptive language)文件的样式来发布的,在WSDL文件里面,包含这个webservice暴露在外面可供使 ...

  7. AFNetworking2.0源码解析<三>

    本篇说说安全相关的AFSecurityPolicy模块,AFSecurityPolicy用于验证HTTPS请求的证书,先来看看HTTPS的原理和证书相关的几个问题. HTTPS HTTPS连接建立过程 ...

  8. AFNetworking2.0源码解析<一>

    本篇先看看AFURLConnectionOperation,AFURLConnectionOperation继承自NSOperation,是一个封装好的任务单元,在这里构建了NSURLConnecti ...

  9. Java并发(基础知识)——显示锁和同步工具类

    显示锁                                                                                     Lock接口是Java ...

  10. maven 依赖显示红线 pom文件不显示红线的一种可能问题

    pom文件引用的是CDH的jar包 而没有配置CDH的仓库 导致maven找不到资源  ,依赖显示红色波浪,并且在仓库内生成了一堆.lastupdate文件 解决: 1. 删除本地仓库内所有的.las ...