http://www.lydsy.com/JudgeOnline/problem.php?id=3196 (题目链接)

题意

  1.查询k在区间内的排名;2.查询区间内排名为k的值;3.修改某一位值上的数值;4.查询k在区间内的前驱(前驱定义为小于x,且最大的数);5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Solution

  修改不好搞,主席树套树状数组空间炸,最好的选择→_→:线段树套treap。

  对于操作2,我们二分找到一个排名大于$k$的最小的数,然后查询这个数的前驱即可。

细节

  查询前驱和后继的时候要特判一下没有找到的情况。

代码

// bzoj3196
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=50010;
int a[maxn],n,m;
struct node {
int son[2],l,r,w,val,rnd,size,tree;
int& operator [] (int x) {return son[x];}
}; namespace Treap {
int sz;node tr[maxn*50];
void pushup(int x) {
tr[x].size=tr[tr[x][0]].size+tr[tr[x][1]].size+tr[x].w;
}
void rotate(int &x,int p) {
int y=tr[x][p];
tr[x][p]=tr[y][p^1];tr[y][p^1]=x;x=y;
pushup(tr[y][p^1]);pushup(y);
}
void insert(int &k,int x) {
if (!k) {tr[k=++sz].val=x;tr[k].rnd=rand();tr[k].size=tr[k].w=1;return;}
int p=x>tr[k].val;tr[k].size++;
if (x==tr[k].val) {tr[k].w++;return;}
insert(tr[k][p],x);
if (tr[tr[k][p]].rnd>tr[k].rnd) rotate(k,p);
}
void erase(int &k,int x) {
if (!k) return;
if (tr[k].val==x) {
if (tr[k].w>1) {tr[k].w--;tr[k].size--;return;}
if (tr[k][0]*tr[k][1]==0) k=tr[k][0]+tr[k][1];
else rotate(k,tr[tr[k][1]].rnd>tr[tr[k][0]].rnd),erase(k,x);
}
else tr[k].size--,erase(tr[k][x>tr[k].val],x);
}
int rank(int k,int x) {
if (!k) return 0;
if (x<=tr[k].val) return rank(tr[k][0],x);
else return rank(tr[k][1],x)+tr[tr[k][0]].size+tr[k].w;
}
int find(int k,int x) {
if (!k) return -1;
if (tr[tr[k][0]].size<x && x<=tr[tr[k][0]].size+tr[k].w) return tr[k].val;
else if (x<=tr[tr[k][0]].size) return find(tr[k][0],x);
else return find(tr[k][1],x-tr[tr[k][0]].size-tr[k].w);
}
int pref(int k,int x) {return find(k,rank(k,x));}
int suff(int k,int x) {return find(k,rank(k,x+1)+1);}
} namespace Segtree {
node tr[maxn<<2];
void build(int k,int s,int t) {
tr[k].l=s;tr[k].r=t;
for (int i=s;i<=t;i++) Treap::insert(tr[k].tree,a[i]);
if (s==t) return;
int mid=(s+t)>>1;
build(k<<1,s,mid);build(k<<1|1,mid+1,t);
}
void modify(int k,int p,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
Treap::erase(tr[k].tree,a[p]);
Treap::insert(tr[k].tree,val);
if (l==r) return;
if (p<=mid) modify(k<<1,p,val);
else modify(k<<1|1,p,val);
}
int rank(int k,int s,int t,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (s==l && t==r) return Treap::rank(tr[k].tree,val);
if (t<=mid) return rank(k<<1,s,t,val);
else if (s>mid) return rank(k<<1|1,s,t,val);
else return rank(k<<1,s,mid,val)+rank(k<<1|1,mid+1,t,val);
}
int pref(int k,int s,int t,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (s==l && t==r) {
int tmp=Treap::pref(tr[k].tree,val);
return tmp==-1 ? -inf : tmp;
}
if (t<=mid) return pref(k<<1,s,t,val);
else if (s>mid) return pref(k<<1|1,s,t,val);
else return max(pref(k<<1,s,mid,val),pref(k<<1|1,mid+1,t,val));
}
int suff(int k,int s,int t,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (s==l && t==r) {
int tmp=Treap::suff(tr[k].tree,val);
return tmp==-1 ? inf : tmp;
}
if (t<=mid) return suff(k<<1,s,t,val);
else if (s>mid) return suff(k<<1|1,s,t,val);
else return min(suff(k<<1,s,mid,val),suff(k<<1|1,mid+1,t,val));
}
int find(int s,int t,int k) {
int l=0,r=1e8,res;
while (l<=r) {
int mid=(l+r)>>1;
if (rank(1,s,t,mid)>=k) r=mid-1,res=mid;
else l=mid+1;
}
return pref(1,s,t,res);
}
}
using namespace Segtree; int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for (int op,x,y,k,i=1;i<=m;i++) {
scanf("%d%d%d",&op,&x,&y);
if (op==1) scanf("%d",&k),printf("%d\n",rank(1,x,y,k)+1);
if (op==2) scanf("%d",&k),printf("%d\n",find(x,y,k));
if (op==4) scanf("%d",&k),printf("%d\n",pref(1,x,y,k));
if (op==5) scanf("%d",&k),printf("%d\n",suff(1,x,y,k));
if (op==3) modify(1,x,y),a[x]=y;
}
return 0;
}

【bzoj3196】 Tyvj1730—二逼平衡树的更多相关文章

  1. BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】

    BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...

  2. [BZOJ3196][Tyvj1730]二逼平衡树

    [BZOJ3196][Tyvj1730]二逼平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询 \(k\) 在区间内的排名 查询区间内排名为 \ ...

  3. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  4. bzoj3196 [TYVJ1730]二逼平衡树 树套树 线段树套替罪羊树

    人傻自带大常数 二分的可行性证明: 贴近他的正确答案不会被当作次优解删掉,因为,若二分在他右边发生,那么二分一定会把左边作为优解,左边同理,所以他一定是被扣掉的所以最后一个小于等于一定是正确答案 #i ...

  5. bzoj3196:Tyvj1730二逼平衡树

    传送门 暴力啊,直接树套树上啊 线段树套splay,卡卡常就直接A了 代码: #include<cstdio> #include<iostream> #include<a ...

  6. [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

    传送门 至少BZOJ过了,其他的直接弃. 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的 ...

  7. 【BZOJ3196】二逼平衡树(树状数组,线段树)

    [BZOJ3196]二逼平衡树(树状数组,线段树) 题面 BZOJ题面 题解 如果不存在区间修改操作: 搞一个权值线段树 区间第K大--->直接在线段树上二分 某个数第几大--->查询一下 ...

  8. [TYVJ1730]二逼平衡树

    [TYVJ1730]二逼平衡树 题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查 ...

  9. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

随机推荐

  1. UML类图(Unified Modeling Language Class Diagrams)

    统一建模语言(UML) |  类图 什么是UML? UML是一种用于可视化描述系统,具有广泛用途的建模语言.作为一种标准化的图形语言,在软件工业中被用于软件系统部件的具体化,可视化,结构化描述以及撰写 ...

  2. laravel 5.5 《电商实战 》辅助函数

    Laravel 提供了很多 辅助函数,有时候我们也需要创建自己的辅助函数. 这里介绍了 tinker,一个laravel内置的php交互式控制台,方便调试php代码 php artisan tinke ...

  3. kettle学习笔记(七)——kettle流程步骤与应用步骤

    一.概述 流程主要用来控制数据流程与数据流向 应用则是提供一些工具类 二.流程步骤 1.ETL元数据注入 类似Java中的反射,在设计时不知道文件名.文件位置等,在真正执行时才知道具体的一些配置等信息 ...

  4. 2017-2018 Exp9 网络欺诈技术防范 20155214

    目录 Exp9 网络欺诈技术防范 实验内容 Webgoat General Access Control Flaws Crossing-Site Scripting Injection Flaws 知 ...

  5. 20155330 《网络对抗》 Exp6 信息搜集与漏洞扫描

    20155330 <网络对抗> Exp6 信息搜集与漏洞扫描 基础问题回答 哪些组织负责DNS,IP的管理? 互联网名称与数字地址分配机构(The Internet Corporation ...

  6. 滚动条ScrollViewer防止滚动时按内容跳跃式滚动的设置

    原文:滚动条ScrollViewer防止滚动时按内容跳跃式滚动的设置 属性中将CanContentScroll设置为False,滚动时就不会跳了,会连续的滚动

  7. [BZOJ4082][Wf2014]Surveillance[倍增]

    题意 给你一个长度为 \(len\) 的环,以及 \(n\) 个区间,要你选择尽量少的区间,使得它们完全覆盖整个环.问最少要多少个区间. \(len,n\leq 10^6\) . 分析 考虑普通的区间 ...

  8. JavaScript快速入门-ECMAScript本地对象(Number)

    Number 对象是原始数值的包装对象. 创建一个Number对象:var myNum=new Number(value); 注意: 1.参数 value 是要创建的 Number 对象的数值,或是要 ...

  9. X32位 天堂2 二章/三章 服务端协议号修改方法

    [本方法适合于2004-2006年之间天堂2由初章服务端修改至二章.三章端时协议号匹配问题]服务端版本位32位初章服务端 目前大部分SF用的协议号情况: 服务端是419 客户端是 417 419 42 ...

  10. Call actvity after viewpager is finished

    private OnPageChangeListener mListener = new OnPageChangeListener() { @Override public void onPageSe ...