题目大意:给你一堆数,每次询问区间[l,r]中离p第k小的|ai-p|

题解:考虑二分答案,对于每个可能的答案,我们只需要看在区间[l,r]里是否有≥k个比二分的答案还要接近于p的

考虑下标线段树,并将其可持久化,线段树i存储1~i中每个数有几个

因为数比较大,考虑离散化,这样最多1e5个数,可以接受

判断时只需要查找第r棵线段树和第l-1棵线段树的区间[l,r]中位于[p-k,p+k]的数有几个然后将返回的值相减看是否≥k即可,注意这里有一些细节

时间复杂度O(mlog^2n)

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
int T,n,m,ans;
struct node
{
int v,bh;
}a[];
bool cmp(const node &T1,const node &T2){return T1.v<T2.v;}
bool cmp2(const node &T1,const node &T2){return T1.bh<T2.bh;}
int L[],R[]; int head[],lson[*],rson[*],cnt[*],tn;
void insert(int l,int r,int p,int now)
{
if(l==r && l==p){cnt[now]++;return;}
int mid=l+r>>;
if(p<=mid)
{
tn++;
lson[tn]=lson[lson[now]];
rson[tn]=rson[lson[now]];
cnt[tn]=cnt[lson[now]];
lson[now]=tn;
insert(l,mid,p,lson[now]);
}
else
{
tn++;
lson[tn]=lson[rson[now]];
rson[tn]=rson[rson[now]];
cnt[tn]=cnt[rson[now]];
rson[now]=tn;
insert(mid+,r,p,rson[now]);
}
cnt[now]=cnt[lson[now]]+cnt[rson[now]];
}
void init()
{
tn=;
for(int i=;i<=n;i++)
{
head[i]=++tn;
lson[head[i]]=lson[head[i-]];
rson[head[i]]=rson[head[i-]];
cnt[head[i]]=cnt[head[i-]];
insert(,n,L[a[i].v],head[i]);
}
}
int ask(int l,int r,int al,int ar,int now)
{
if(al>ar) return ;
if(l==al && r==ar)return cnt[now];
int mid=l+r>>;
if(ar<=mid)return ask(l,mid,al,ar,lson[now]);
if(al>mid)return ask(mid+,r,al,ar,rson[now]);
return ask(l,mid,al,mid,lson[now])+ask(mid+,r,mid+,ar,rson[now]);
} int aa,bb,val,k;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(L,,sizeof(L));
memset(R,,sizeof(R));
ans=;
for(int i=;i<=n;i++){scanf("%d",&a[i].v);a[i].bh=i;}
sort(a+,a++n,cmp);
for(int i=;i<=n;i++)if(!L[a[i].v])L[a[i].v]=R[a[i].v]=i;
for(int i=;i<=;i++)if(R[i-]> && R[i]==)R[i]=R[i-];
for(int i=;i>;i--)if(L[i+]> && L[i]==)L[i]=L[i+];
sort(a+,a++n,cmp2);
init();
while(m--)
{
scanf("%d%d%d%d",&aa,&bb,&val,&k);
aa^=ans;bb^=ans;val^=ans;k^=ans;
int l=,r=,mid,tl,tr;
while(l<r)
{
mid=l+r>>;
tl=val-mid;tr=val+mid;
tl=max(tl,);tr=min(tr,);
if(R[tr]<L[tl] || R[tr]== || L[tl]==){l=mid+;continue;}
int t1=ask(,n,L[tl],R[tr],head[bb]),t2=;
if(aa>)t2=ask(,n,L[tl],R[tr],head[aa-]);
if(t1-t2<k)l=mid+;
else r=mid;
}
printf("%d\n",r);
ans=r;
}
}
return ;
}

心得:考场上很快就想到做法,但是被卡了很久,因为数组没开够。。第一次见到*200的线段树,不知道什么原因开这么大,欠缺思考

实际上*20能过,只不过考场上可能数据出锅或者评测机出锅导致没过,赛后重测过了

【HDU6621】K-th Closest Distance【线段树】的更多相关文章

  1. HDU - 6621 K-th Closest Distance 主席树+二分答案

    K-th Closest Distance 主席树第二波~ 题意 给你\(n\)个数\(m\)个询问,问\(i\in [l,r]\)计算每一个\(|a_{i}-p|\)求出第\(k\)小 题目要求强制 ...

  2. D. Closest Equals(线段树)

    题目链接: D. Closest Equals time limit per test 3 seconds memory limit per test 256 megabytes input stan ...

  3. POJ- 2104 hdu 2665 (区间第k小 可持久化线段树)

    可持久化线段树 也叫函数式线段树也叫主席树,其主要思想是充分利用历史信息,共用空间 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html 这个博客总 ...

  4. P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)

    P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树 把插入的值离散化一下开个线段树 蓝后每个节点开个线段树,维护一下每个数出现的区间和次数 为了防止MLE动态开点就好辣 重点是标记永久 ...

  5. 序列内第k小查询(线段树)

    最近请教了一下大佬怎么求序列内第k大查询,自己又捣鼓了一下,虽然还没有懂得区间第k大查询,不过姑且做一个记录先吧 因为每个元素大小可能很大而元素之间不连续,所以我们先离散化处理一下,程序中的ori[ ...

  6. BZOJ3110 K大数查询 【线段树 + 整体二分 或 树套树(非正解)】

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

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

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

  8. 2019HDU多校第四场 K-th Closest Distance ——主席树&&二分

    题意 给定 $n$ 个数,接下来有 $q$ 次询问,每个询问的 $l, r, p, k$ 要异或上一次的答案,才是真正的值(也就是强制在线).每次询问,输出 $[l, r]$ 内第 $k$ 小的 $| ...

  9. 区间第K小——可持久化线段树模板

    概念 可持久化线段树又叫主席树,之所以叫主席树是因为这东西是fotile主席创建出来的. 可持久化数据结构思想,就是保留整个操作的历史,即,对一个线段树进行操作之后,保留访问操作前的线段树的能力. 最 ...

随机推荐

  1. pycharm常用快捷键 --- keymap==ecplise

    F5 进入函数逐行调试 F6 执行完一行代码 F8 执行到下一个断点处 ctrl + d    --删除一行代码 ALT + 上/下 箭头   代码上下移动 ALT + 左/右 箭头    左--返回 ...

  2. python实现自动发送邮件

    Python发送邮件成功的前提,应是先开启授权码.目前使用广泛的邮箱有:163邮箱.qq邮箱等. 163邮箱开启授权码的方法如下图: qq邮箱开启授权码的方法如下图: 接下来代码的实现: import ...

  3. 【题解】4879. 【NOIP2016提高A组集训第11场11.9】少女觉

    Description 在幽暗的地灵殿中,居住着一位少女,名为古明地觉.据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心.掌控人心者,可控天下. 咳咳.人的记忆可以被描述为一 ...

  4. 合并石子(区间DP)

    有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子合并成一堆的总花费最小. 区间DP思想:现在小区间进行DP得到最优解, ...

  5. package和import语句_5

    J2SDK中主要的包介绍   java.lang—包含一些Java语言的核心类,如String.Math.Integer.System和 Thread,提供常用功能. java.awt—包含了构成抽象 ...

  6. DS静态查找- 顺序-二分-索引

    静态查找 静态表是只执行查找操作,而不执行插入.删除等操作的表. 现在常说的有五大查找方法:顺序查找.分块查找.索引查找.树查找.哈希查找. 后两种之前写过了二叉查找树和哈希表,现在回顾前面三种,它们 ...

  7. 通过JS,用a标签代替form中的submit

    ---恢复内容开始--- 有时候在使用表单的时候,不一定会用到表单中的input_submit来提交表单数据,可能会用a.button等来代替 然后自然而然地想到了用JS中的提交表单数据的动作 < ...

  8. Java中的多线程基础

    1.线程与进程 进程: 进程是程序运行以及资源分配的基本单位,一个程序至少有一个进程. 如下图所示: 线程: 线程是CPU调度和分配的基本单位,一个进程至少有一个线程. 同一个进程中的线程共享进程资源 ...

  9. kmp(多次可重叠匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=1686 Oulipo Problem Description The French author Georges ...

  10. vmware linux root密码破解

    centOS: 1.开机过程按上下箭头键,让系统不要进入到引导程序中, 2.按 'e' 进入到编辑模式 3.找到linux16开始的首行,在末尾加入'rw init=/bin/sh' (会出现修改密码 ...