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个位置,每个位置可以看做一个集合. ...
随机推荐
- CentOS7 源进源出
echo 200 ct >> /etc/iproute2/rt_tablesecho 201 cu >> /etc/iproute2/rt_tables ip route ad ...
- 区间动态规划 矩阵连乘 Medium
The multiplication puzzle is played with a row of cards, each containing a single positive integer. ...
- PY个欧拉筛
大数据用 python? 速度感人 突然来了一发 python 欧拉筛,调了半天之后输入 1e7 过了几秒钟之后出解了,PY 果然神速 没学过 PY 的小同学可以当做 VB 的阅读程序,反正语言隔离都 ...
- C++设计模式:访客模式
访客模式:通俗的说, 就是定义一个访问者角色, 当对指定角色进行访问时要通过访问者进行访问. 访客模式的侵入性适中,仅在被访问的类里面加一个对外提供接待访问者的接口. 访客模式的优点: 符合单一职责原 ...
- HTML-图片和多媒体
1.图片和多媒体 (1) 图片:img元素 src 属性:图片路径: alt 属性:图片无法显示时使用的替代文字: title:鼠标悬停时显示的文字 : <img src="图片 ...
- Linux系统性能测试工具(二)——内存压力测试工具memtester
本文介绍关于Linux系统(适用于centos/ubuntu等)的内存压力测试工具-memtester.内存性能测试工具包括: 内存带宽测试工具——mbw: 内存压力测试工具——memtester: ...
- docker配置Nginx
创建及进入docker容器$docker run -p 80 --name web01 -i -t ubuntu /bin/bash 创建html文件夹$mkdir -p /var/www/html ...
- tp5 模板参数配置(模板静态文件路径)
tp5 模板参数配置(模板静态文件路径) // 模板页面使用 <link rel="stylesheet" type="text/css" href=&q ...
- TreeView详细用法
Treeview用于显示按照树形结构进行组织的数据. Treeview控件中一个树形图由节点(TreeNode)和连接线组成.TtreeNode是TTreeview的基本组成单元. ...
- 2014百度之星初赛第二场hdu 4831 Scenic Popularity
Scenic Popularity Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...