2019HDU多校第四场 K-th Closest Distance ——主席树&&二分
题意
给定 $n$ 个数,接下来有 $q$ 次询问,每个询问的 $l, r, p, k$ 要异或上一次的答案,才是真正的值(也就是强制在线)。每次询问,输出 $[l, r]$ 内第 $k$ 小的 $|p-a[i]|$.
分析
通常主席树用来求区间第K大,其实它的实际作用是统计某个区间内值的个数。所以,
对于每次询问,对答案进行二分,对于可能的答案 $x$,对 $R_l \sim R_r$ 的线段树查找 $[p-x, p+x]$ 的是否为 $k$.
主席树中在值上建立的,这题数据范围为 $10^6$,不需要离散化(话说强制在线的离散化我也不会)
感觉有些卡常,32倍、55倍的空间都TLE,改成64倍就过了(为啥啊)
#include<bits/stdc++.h>
using namespace std; const int maxn = 1e5 + ;
int n, m;
//int a[maxn];
//int rt[maxn], lc[maxn << 5], rc[maxn << 5], sum[maxn << 5]; //rt:不同版本的根节点 lc/rc: 左儿子、右儿子(公用) sum: 和(公用)
int rt[maxn], lc[maxn*], rc[maxn*], sum[maxn*];
int node_cnt; //node总计数, pnt_disc: A中数字对应B中的值
int range = ; //数据范围,也就是线段树的大小 void build(int& last_node, int l, int r)
{
last_node = ++ node_cnt;
sum[last_node] = ;
if(l == r) return;
int mid = (l + r) >> ;
build(lc[last_node], l, mid);
build(rc[last_node], mid+, r);
} int modify(int pre_rt, int v, int l, int r)
{
int new_rt = ++node_cnt;
lc[new_rt] = lc[pre_rt];
rc[new_rt] = rc[pre_rt];
sum[new_rt] = sum[pre_rt] + ; int mid = (l + r) >> ;
if(l == r) return new_rt;
if(mid >= v) lc[new_rt] = modify(lc[new_rt],v, l, mid);
else rc[new_rt] = modify(rc[new_rt], v, mid+, r);
return new_rt;
} //查询[ql, qr]中不同元素个数
int query(int rt1, int rt2, int ql, int qr, int l, int r)
{
//printf("rt1:%d rt2:%d k:%d l:%d r:%d ", rt1, rt2, k, l, r);
if(ql <= l && r <= qr) return sum[rt2]-sum[rt1]; int mid = (l + r) >> ;
int ans = ;
if(ql <= mid) ans += query(lc[rt1], lc[rt2], ql, qr, l, mid);
if(qr > mid) ans += query(rc[rt1], rc[rt2], ql, qr, mid+, r);
return ans;
} void print_debug()
{
printf("node_cnt: %d\n", node_cnt);
for(int i = ;i <= node_cnt;i++)
printf("%d lc:%d rc:%d sum:%d\n", i, lc[i], rc[i], sum[i]);
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m); node_cnt = ;
build(rt[], , range);
for(int i = ;i <= n;i++)
{
int tmp;
scanf("%d", &tmp);
rt[i] = modify(rt[i-], tmp, , range); //只在上一个版本的基础上修改
} int ans = ;
for(int i = ;i <m;i++)
{
int l, r, p, k;
scanf("%d%d%d%d", &l, &r, &p, &k);
l ^= ans; r ^= ans;
p ^= ans; k ^= ans;
if(l > r) swap(l, r); int L = , R = range; //
while(L <= R)
{
int M = L + (R-L)/;
if(query(rt[l-], rt[r], max(, p-M), min(p+M, range), , range) >= k)
{
ans = M;
R = M-;
}
else L = M+;
}
printf("%d\n", ans);
}
}
}
[ Copy to Clipboard ] [ Save to File]
参考链接:
1. https://blog.csdn.net/birdmanqin/article/details/97964662
2. http://morecoder.com/article/1254619.html
2019HDU多校第四场 K-th Closest Distance ——主席树&&二分的更多相关文章
- [2019杭电多校第四场][hdu6621]K-th Closest Distance(主席树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意为求区间[l,r]内第k小|a[i]-p|的值. 可以二分答案,如果二分的值为x,则判断区间 ...
- 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)
K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...
- 2019HDU多校第四场题解
1001.AND Minimum Spanning Tree 传送门:HDU6614 题意:给你一个又n个点的完全图,点编号从1~n,每条边的权值为被连接的两点编号按位与后的值.现在要你找到最小生成树 ...
- 2019HDU多校第四场 Just an Old Puzzle ——八数码有解条件
理论基础 轮换与对换 概念:把 $S$ 中的元素 $i_1$ 变成 $i_2$,$i_2$ 变成 $i_3$ ... $i_k$ 又变成 $i_1$,并使 $S$ 中的其余元素保持不变的置换称为循环, ...
- 2019HDU多校第三场 K subsequence——最小费用最大流
题意 给定一个 $n$ 个整数的数列,从中至多选取 $k$ 个上升子序列(一个元素最多被选一次),使得选取的元素和最大. 分析 考虑这个问题和经典网络流问题“最长不下降子序列”相似,我们考虑对这个建图 ...
- [2019HDU多校第四场][HDU 6617][D. Enveloping Convex]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6617 题目大意:给出一凸包\(P\),求最小的与\(P\)相似且对应边平行的多边形,使得题目给出的\( ...
- 2019牛客多校第四场K number dp or 思维
number 题意 给一个数字串,问有几个子串是300的倍数 分析 dp写法:这题一看就很dp,直接一个状态dp[i][j]在第i位的时候膜300的余数是j左过去即可.这题比赛的时候样例老是少1,后面 ...
- 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)
题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...
- 2018 HDU多校第四场赛后补题
2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...
随机推荐
- 微信小程序的网络重试机制
最近在开发微信小程序, 在测试时, 总能碰到一些诸如网络被打断啊之类的问题. 小程序是一款实时互动的小程序, 基于一系列原因, 没有使用Socket, 而是使用的是长链接. 所以对这类问题不能大意啊, ...
- js文本公告滚动展示,图片轮播....
1.引入文件 <link rel="stylesheet" href="/css/liMarquee.css"> <script src=&q ...
- Spring boot+Websocket实例1
简单的demo https://github.com/callicoder/spring-boot-websocket-chat-demo
- java积累的细节问题
一.将几个数字进行拼接,拼接成字符串 一定要将""放到几个数字之前,否则就会把数字相加之后的数转化成字符串 如你需要拼接年份,月份,和日 如果:2018+12+13+"& ...
- Linux精简版系统安装网络配置问题解决
参考文档:https://www.jianshu.com/p/7579a2ad1c92 通过链接中的文档配置linux系统的时候,在执行命令yum install net-tools的这里提示错误,是 ...
- 利用Python进行数据分析_Numpy_基础_2
Numpy数据类型包括: int8.uint8.int16.uint16.int32.uint32.int64.uint64.float16.float32.float64.float128.co ...
- Python之字符与编码笔记
概述 类型 str 字符串 bytes 字节 bytearray 字节数组 字符串编码架构 字符集:赋值一个编码到某个字符,以便在内存中表示 编码 Ecoding:转换字符到原始字节形式 解码 Dec ...
- SAS学习笔记27 卡方检验
卡方检验(chi-square test)是英国统计学家Pearson提出的一种主要用于分析分类变量数据的假设检验方法,该方法主要目的是推断两个或多个总体率或构成比之间有无差别. 卡方分布界值表的依据 ...
- msyql 去重
delete from userinfo where busi_id in (select busi_id from (select busi_id from userinfo group by bu ...
- ubuntu 快捷方式添加 applications添加
首先我们要了解,Ubuntu 的 Dash 里所有程序都是在 /usr/share/applications 中的,所以我们的思路很简单——建一个类似于“快捷方式”一样的东西扔进去就好了.所以第一步自 ...