HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)
时间:2019-09-18
本文章向大家介绍HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分),主要包括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+10; 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)>>1; build(lson[rt],l,mid); build(rson[rt],mid+1,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]+1; if(l==r) return ; int mid=(l+r)>>1; if(p<=mid) updata(lson[root],lson[rt],p,l,mid); else updata(rson[root],rson[rt],p,mid+1,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)>>1; int ans=0; if(l<=mid) ans+=query(lson[rt_],lson[rt],L,mid,l,r); if(mid<r) ans+=query(rson[rt_],rson[rt],mid+1,R,l,r); return ans; } int main(){ int _;scanf("%d",&_); while(_--){ int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x;scanf("%d",&x); updata(tr[i-1],tr[i],x,1,N); } int T=0; for(int i=1;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=0,RR=1e6,ans=0; while(LL<=RR){ int mid=(LL+RR)>>1; int l=max(1,p-mid); int r=min(N,p+mid); if(query(tr[R],tr[L-1],1,N,l,r)>=k){ RR=mid-1;ans=mid; } else LL=mid+1; } T=ans; printf("%d\n",ans); } } return 0; }
权值线段树的做法:
要解决的问题依然没有变;
线段树的每个节点都存着对应区间有序的序列,比如{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+10; 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)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } 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=0; int mid=(L+R)>>1; if(l<=mid) ans+=query(L,mid,rt<<1,l,r,val); if(mid<r) ans+=query(mid+1,R,rt<<1|1,l,r,val); return ans; } int main(){ int _; scanf("%d",&_); while(_--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); int L1=0,R1=0,p1=0,k1=0; int T=0; for(int i=1;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=0,RR=1e6,ans=0; while(LL<=RR){ int mid=(LL+RR)>>1; int K=query(1,n,1,L,R,p+mid)-query(1,n,1,L,R,p-mid-1); if(K>=k) {RR=mid-1;ans=mid;} else LL=mid+1; } printf("%d\n",ans); T=ans; } } return 0; }
原文地址:https://www.cnblogs.com/shuaihui520/p/11541240.html
- 【最新TensorFlow1.4.0教程03】利用Eager Execution构建和训练卷积神经网络(CNN)
- 360护心镜脚本分析及N种绕过方式
- 清北集训Day6T1(生成函数)
- 变种XSS:持久控制
- 洛谷P1291 [SHOI2002]百事世界杯之旅(期望DP)
- 新型XSS总结两则
- 设计一个有getMin功能的栈
- BZOJ4832: [Lydsy1704月赛]抵制克苏恩(期望DP)
- 基于连通性状态压缩的动态规划问题
- 常见Flash XSS攻击方式
- BZOJ2134: 单选错位(期望乱搞)
- 详解斯坦纳点及斯坦纳树及模版归纳总结
- 浅谈错排公式的推导及应用
- BZOJ3143: [Hnoi2013]游走(期望DP 高斯消元)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ubuntu14.04安装jdk1.8的教程
- Linux nohup实现后台运行程序及查看(nohup与&)
- 详解Linux 服务管理两种方式service和systemctl
- CentOS6.5安装python3.7详细步骤
- Centos7.5配置IP地址的实现
- linux里daily_routine实例代码详解
- 类Linux环境安装jdk1.8及环境变量配置详解
- CentOS7yum安装PHP7.2的操作方法
- CentOS 7中 Apache Web 服务器安装配置教程
- Win10安装Linux系统的教程图解
- 浅谈ubuntu执行.sh文件几种方式区别
- CentOS7使用yum安装PostgreSQL和PostGIS的方法
- Linux Windows下设置定时执行任务的方法
- 详解ssh免密码登录配置方法(图示加命令)
- centos 7 修改sshd | 禁止 root登录及sshd端口脚本定义