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. c# Findwindow sendMessage

    using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServi ...

  2. 20155238 实验四 Android程序设计

    Android 安装Android Studio 按照教程依次完成安装步骤.安装所存的相应文件夹必须纯英文,不能出现特殊字符. 32位系统和64位系统是同一个安装文件.启动程序中32位与64位都有.根 ...

  3. SCC的奇葩算法——Kosaraju

    不会Tarjan,难道就不能与邪恶的SCC作斗争了吗? 祭出Kosaraju. 一些变量名的意义: a[N] 原图的vector存储 b[N] 原图的所有边反向vector存储 s dfs得出的拓扑序 ...

  4. 外部事件/中断的区别及EXTI->SWIER的用途

    EXTI_SWIER作用:允许我们通过程序控制就可以启动中断/事件线 1.产生事件的线路最终的产物是一个脉冲信号,这个脉冲信号可以给其他外设电路使用,比如定时器TIM.模拟数字转换器ADC等等. 2. ...

  5. 5.Xilinx RapidIO核例子工程源码分析

    https://www.cnblogs.com/liujinggang/p/10091216.html 一.软件平台与硬件平台 软件平台: 操作系统:Windows 8.1 64-bit 开发套件:V ...

  6. maven mvn package 打包项目时,出现错误导致失败的解决方法

    解决思路:看报错时在maven打包过程中的哪一步,然后看报错内容,解决报错内容即可,如果是实在不好解决的部分,看看能不能设置不检测,能打包出来就行. 这里是因为mybatis逆向工程插件出现异常所以中 ...

  7. eclipse中怎么找项目部署的路径和找编译后的class路径

    1.快捷键 ctrl+shift+R,会默认显示你的源文件.java的路径,如果没有.class的话,点击右上角的三角,选中  Show Derived Resource; 2.打开出现下图 3.按下 ...

  8. [摘抄]从 GitHub 身上学到的 3 个创业经验

    1.找一个大问题去解决 让 Git 更容易使用是 GitHub 的目标,但它从来不是 GitHub 的最终目标.GitHub 的真正目标是让协作和编写软件变得更容易.世界上每一个软件开发者都在努力解决 ...

  9. Vue.js 相关知识(路由)

    1. 简介 路由,工作原理与路由器相似(路由器将网线总线的IP分发到每一台设备上),Vue中的路由根据用户在网页中的点击,将其引导到对应的页面. 2. 使用步骤 安装vue-router或者直接引入v ...

  10. linux gcc编译多个源文件的方法

    http://blog.csdn.net/yinjiabin/article/details/7731817