题意

给定 $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 ——主席树&&二分的更多相关文章

  1. [2019杭电多校第四场][hdu6621]K-th Closest Distance(主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意为求区间[l,r]内第k小|a[i]-p|的值. 可以二分答案,如果二分的值为x,则判断区间 ...

  2. 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

    K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...

  3. 2019HDU多校第四场题解

    1001.AND Minimum Spanning Tree 传送门:HDU6614 题意:给你一个又n个点的完全图,点编号从1~n,每条边的权值为被连接的两点编号按位与后的值.现在要你找到最小生成树 ...

  4. 2019HDU多校第四场 Just an Old Puzzle ——八数码有解条件

    理论基础 轮换与对换 概念:把 $S$ 中的元素 $i_1$ 变成 $i_2$,$i_2$ 变成 $i_3$ ... $i_k$ 又变成 $i_1$,并使 $S$ 中的其余元素保持不变的置换称为循环, ...

  5. 2019HDU多校第三场 K subsequence——最小费用最大流

    题意 给定一个 $n$ 个整数的数列,从中至多选取 $k$ 个上升子序列(一个元素最多被选一次),使得选取的元素和最大. 分析 考虑这个问题和经典网络流问题“最长不下降子序列”相似,我们考虑对这个建图 ...

  6. [2019HDU多校第四场][HDU 6617][D. Enveloping Convex]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6617 题目大意:给出一凸包\(P\),求最小的与\(P\)相似且对应边平行的多边形,使得题目给出的\( ...

  7. 2019牛客多校第四场K number dp or 思维

    number 题意 给一个数字串,问有几个子串是300的倍数 分析 dp写法:这题一看就很dp,直接一个状态dp[i][j]在第i位的时候膜300的余数是j左过去即可.这题比赛的时候样例老是少1,后面 ...

  8. 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)

    题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...

  9. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

随机推荐

  1. SQLite基础-1.SQL简介

    目录 一.SQLite简介 二.SQLite命令 三.SQLite安装 在 Windows 上安装 SQLite 四.SQLite 点命令 一.SQLite简介 最近在使用Python+Flask框架 ...

  2. python学习-24 局部变量与全局变量

    局部变量与全局变量 1.没有缩进的变量,为全局变量 name = 'jphn' 在子程序里定义的变量,局部变量 2. name = 'jphn' #全局变量 def a(): name='andy' ...

  3. python学习-11 运算符2

    布尔值 1.真 true 假false name = 'abc' c = 'c' in name print(c) 运算结果: True Process finished with exit code ...

  4. Anaconda安装报错

    通用解决方案:先卸载,然后重新安装(注意安装路径全英文且不要有空格),勾选添加环境变量选项

  5. goroutine基础

    程序1: package main import ( "fmt" "time" ) func test () { var i int for { fmt.Pri ...

  6. Junit 学习笔记

    目录 Junit 学习笔记 1. 编写测试用例时需要注意 2. 出现结果分析 3. Junit 运行流程 4. Junit 常用注解 5. Junit 测试套件的使用 6. Junit 参数化设置 J ...

  7. (二)ActiveMQ之点对点消息实现

    一.点对点消息实现概念 在点对点或队列模型下,一个生产者向一个特定的队列发布消息,一个消费者从该队列中读取消息.这里,生产者知道消费者的队列,并直接将消息发送到消费者的队列.这种模式被概括为:只有一个 ...

  8. (六)mybatis之多对一关系(简单)

    一.需求分析 需求:   查询所有订单信息及订单下的订单明细信息 分析:      一条订单只能由一个消费者下单,但是一条订单有多条订单明细. 二.创建数据库表和实体对象 Customer.java ...

  9. C#的@标志的使用情况—本篇blog采用Markdown编写

    @(C# 参考--出自官方文档入口) 1.使 C# 关键字用作标识符. @ 字符可作为代码元素的前缀,编译器将把此代码元素解释为标识符而非 C# 关键字. 下面的示例使用 @ 字符定义其在 for 循 ...

  10. 使用swagger在netcorewebapi项目中自动生成文档

    一.背景 随着前后端分离模式大行其道,我们需要将后端接口撰写成文档提供给前端,前端可以查看我们的接口,并测试,提高我们的开发效率,减少无效的沟通.在此情况下,通过代码自动生成文档,这种需求应运而生,s ...