主席树/线段树模拟归并排序+二分答案(好题)——hdu多校第4场08

时间:2023-01-12 22:36:52

用主席树写起来跑的快一点,而且也很傻比,二分答案,即二分那个半径就行

主席树求的是区间<=k的个数

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
int a[maxn],n,m; struct Node{int lc,rc,v;}t[maxn*];
int rt[maxn],tot;
int update(int last,int l,int r,int pos){
int now=++tot;
t[now]=t[last];
t[now].v++;
if(l==r)return now;
int m=l+r>>;
if(pos<=m)
t[now].lc=update(t[last].lc,l,m,pos);
else t[now].rc=update(t[last].rc,m+,r,pos);
return now;
}
int query(int st,int ed,int L,int R,int l,int r){
if(L>R)return ;
if(L<=l && R>=r)return t[ed].v-t[st].v;
int m=l+r>>,res=;
if(L<=m)res+=query(t[st].lc,t[ed].lc,L,R,l,m);
if(R>m)res+=query(t[st].rc,t[ed].rc,L,R,m+,r);
return res;
}
int build(int l,int r){
int now=++tot;
t[now].lc=t[now].rc=t[now].v=;
if(l==r)return now;
int m=l+r>>;
t[now].lc=build(l,m);
t[now].rc=build(m+,r);
return now;
}
void init(){
memset(rt,,sizeof rt);
memset(t,,sizeof t);
tot=;
} int main(){
int t;cin>>t;
while(t--){
init();
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
rt[]=build(,n);
for(int i=;i<=n;i++)
rt[i]=update(rt[i-],,,a[i]); int ans=,l,r,p,k;
while(m--){
scanf("%d%d%d%d",&l,&r,&p,&k);
l^=ans,r^=ans,p^=ans,k^=ans; int L=,R=,mid;ans=;
while(L<=R){
mid=L+R>>;
int res1=query(rt[l-],rt[r],,mid+p,,);
int res2=query(rt[l-],rt[r],,p-mid-,,);
if(res1-res2>=k)
ans=mid,R=mid-;
else L=mid+;
}
cout<<ans<<'\n';
}
}
}

线段树的话就要模拟一下归并排序的过程,即线段树结点维护的是区间的有序序列

然后还是二分答案,然后查询的是区间[l,r]范围内在[p-mid,p+mid]范围内的数个数,要特别注意查询的方式

     int res1=lower_bound(seg[rt].begin(),seg[rt].end(),v1)-seg[rt].begin();
int res2=upper_bound(seg[rt].begin(),seg[rt].end(),v2)-seg[rt].begin();//上界一定要用upper_bound!
return res2-res1;
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 100005
int n,k,l,r,ans,p,m,a[maxn]; #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
vector<int>seg[maxn<<];
void pushup(int rt){
int s=seg[rt<<].size(),t=seg[rt<<|].size(),i=,j=;
while(i!=s && j!=t){
if(seg[rt<<][i]<=seg[rt<<|][j])
seg[rt].push_back(seg[rt<<][i]),i++;
else seg[rt].push_back(seg[rt<<|][j]),j++;
}
while(i!=s){
seg[rt].push_back(seg[rt<<][i]);
i++;
}
while(j!=t){
seg[rt].push_back(seg[rt<<|][j]);
j++;
}
} void build(int l,int r,int rt){
seg[rt].clear();
if(l==r){
seg[rt].push_back(a[l]);return;
}
int m=l+r>>;
build(lson);build(rson);
pushup(rt);
}
int query(int L,int R,int v1,int v2,int l,int r,int rt){
if(L<=l && R>=r){
int res1=lower_bound(seg[rt].begin(),seg[rt].end(),v1)-seg[rt].begin();
int res2=upper_bound(seg[rt].begin(),seg[rt].end(),v2)-seg[rt].begin();
return res2-res1;
}
int m=l+r>>,res=;
if(L<=m)res+=query(L,R,v1,v2,lson);
if(R>m)res+=query(L,R,v1,v2,rson);
return res;
} int judge(int mid){
int res=;//查找半径是mid
res=query(l,r,p,p+mid,,n,);
if(res>=k)return ;
res+=query(l,r,p-mid,p-,,n,);
if(res>=k)return ;
return ;
} int main(){
int t;cin>>t;
while(t--){
n=k=l=r=ans=p=m=; scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,n,); while(m--){
scanf("%d%d%d%d",&l,&r,&p,&k);
l^=ans,r^=ans,p^=ans,k^=ans;
int L=,R=,mid;
ans=;
while(L<=R){//二分半径
mid=L+R>>;
if(judge(mid))
ans=mid,R=mid-;
else L=mid+;
}
cout<<ans<<'\n';
}
}
}

主席树/线段树模拟归并排序+二分答案(好题)——hdu多校第4场08的更多相关文章

  1. cogs 2109&period; &lbrack;NOIP 2015&rsqb; 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分

    2109. [NOIP 2015] 运输计划 ★★★☆   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:3 s   内存限制:256 MB [题 ...

  2. 浅谈树套树&lpar;线段树套平衡树&rpar;&amp&semi;学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

  3. HDU 5649 DZY Loves Sorting(二分答案&plus;线段树&sol;线段树合并&plus;线段树分割)

    题意 一个 \(1\) 到 \(n\) 的全排列,\(m\) 种操作,每次将一段区间 \([l,r]\) 按升序或降序排列,求 \(m\) 次操作后的第 \(k\) 位. \(1 \leq n \le ...

  4. &lbrack;BZOJ4552&rsqb;&lbrack;TJOI2016&amp&semi;&amp&semi;HEOI2016&rsqb;排序&lpar;二分答案&plus;线段树&sol;线段树分裂与合并&rpar;

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  5. &lbrack;CSP-S模拟测试&rsqb;&colon;树(树上上升序列&plus;主席树&plus;线段树)

    题目传送门(内部题78) 输入格式 第一行输入两个整数$n,q$,表示节点数和询问数. 第二行输入$n$个整数$w_i$,表示第$i$个点的智商. 第三行至第$n+1$行每行输入两个数$x,y$,表示 ...

  6. BZOJ3110 &lbrack;Zjoi2013&rsqb;K大数查询 树套树 线段树 整体二分 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...

  7. EC Round 33 F&period; Subtree Minimum Query 主席树&sol;线段树合并

    这题非常好!!! 主席树版本 很简单的题目,给一个按照指定节点的树,树上有点权,你需要回答给定节点的子树中,和其距离不超过k的节点中,权值最小的. 肯定首先一想,按照dfs序列建树,然后按照深度为下标 ...

  8. POJ2104 K-th Number 不带修改的主席树 线段树

    http://poj.org/problem?id=2104 给定一个序列,求区间第k小 通过构建可持久化的点,得到线段树左儿子和右儿子的前缀和(前缀是这个序列从左到右意义上的),然后是一个二分的ge ...

  9. Bzoj 1901&colon; Zju2112 Dynamic Rankings 树套树&comma;线段树&comma;平衡树&comma;Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

随机推荐

  1. BZOJ 3110 &lbrack;Zjoi2013&rsqb;K大数查询 ——整体二分

    [题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...

  2. js 之 continue break return 用法及注意事项

    1,continue continue有两种用法: 1,continue; 这种用法必须包含在循环里,否则报错,例子: for(var i=0;i<10;i++){ if(i%2===0){ c ...

  3. 3&period;IP地址分类&lowbar;规划&lowbar;子网掩码

    IP地址分类_规划_子网掩码 3.1MAC地址 网卡的身份证号———MAC地址 MAC地址的长度为48位(6个字节),通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如:08:00:20: ...

  4. HTTP响应头和请求头信息对照表

    HTTP请求头提供了关于请求,响应或者其他的发送实体的信息.HTTP的头信息包括通用头.请求头.响应头和实体头四个部分.每个头域由一个域名,冒号(:)和域值三部分组成. 通用头标:即可用于请求,也可用 ...

  5. ABAP 常用FUNCTION集锦(转)

    此文章从网上抄摘,目的用于自己记录 DYNP_VALUES_READ – 读取SCREEN字段的值,也可以用来读取报表SELECTION SCREEN. DYNP_VALUES_UPDATE – 更新 ...

  6. datables的基本操作

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  7. shell脚本实现telnet测试服务端口

    备注,使用方法:当前目录下要存在需要测试的地址端口的文件ip.txt,例子:cat ip.txt141.12.65.17 7500 #!/bin/bashcur_dir=$(pwd)ipfile=$c ...

  8. oracle 中 dblink 的简单使用

    oracle 中 dblink 的简单使用 dblink的作用 当用户要跨本地数据库,访问另外一个数据库表中的数据时,本地数据库中必须创建了远程数据库的dblink,通过dblink本地数据库可以像访 ...

  9. bootstrap导航条等样例持续更新》。。

    1.导航条 <!-- 导航条 --> <nav class="navbar navbar-static-top navbar-inverse"> <d ...

  10. 换行符在HTML中直接替换为&lt&semi;br&gt&semi;

         #set($text=$!obj.getMeasure().replaceAll("\r\n","<br>"))     <td a ...