【模板】二逼平衡树(树套树)

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

查询k在区间内的排名

查询区间内排名为k的值

修改某一位值上的数值

查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)

查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)

注意上面两条要求和tyvj或者bzoj不一样,请注意

输入输出格式

输入格式:

第一行两个数 n,m 表示长度为n的有序序列和m个操作

第二行有n个数,表示有序序列

下面有m行,opt表示操作标号

若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名

若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数

若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k

若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱

若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

输出格式:

对于操作1,2,4,5各输出一行,表示查询结果

说明

时空限制:2s,1256M

\(n,m \leq 5\cdot {10}^4\)

保证有序序列所有值在任何时刻满足\([0, {10} ^8]\)

题目来源:bzoj3196 / Tyvj1730 二逼平衡树,在此鸣谢

此数据为洛谷原创。(特别提醒:此数据不保证操作4、5一定存在,故请务必考虑不存在的情况)


前几天写了个树状数组套平衡树,最后懒得调了

花了很久写+调弄了树状数组套可持久化线段树

发现有思想的是 在多个可持久化树上一起二分

很烦人的是查排名时的一些存在性问题

最关键的是权值线段树想离散开点还必须离线

代码也不好看,以后还会写的


Code

#include <cstdio>
#include <algorithm>
#define sf num[i].second.first
#define ss num[i].second.second
using namespace std;
const int N=300010;
const int inf=2147483647;
int sum[N*50],ls[N*50],rs[N*50],root[N],las[N],tot,n,m,is,n_,n0,dat[N<<1];
pair <int,pair<int,int> > num[N<<1];
struct node
{
int opt,l,r,k;
}op[N];
void change(int &now,int l,int r,int pos,int delta)
{
if(!now) now=++tot;
sum[now]+=delta;
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid) change(ls[now],l,mid,pos,delta);
else change(rs[now],mid+1,r,pos,delta);
}
int query(int now,int l,int r,int pos)//1-pos的值
{
if(l==r)
return is=sum[now],0;
if(!now||!pos) return sum[now];
int mid=l+r>>1;
if(pos<=mid) return query(ls[now],l,mid,pos);
else return sum[ls[now]]+query(rs[now],mid+1,r,pos);
}
void add(int x,int pos,int delta)
{
while(x<=n_)
{
change(root[x],1,n,pos,delta);
x+=x&-x;
}
}
int Rank(int l,int r,int pos)//查询l-r区间pos的排名
{
if(!pos) return 0;
int rk=0,cnt0=0;
for(int i=l-1;i;i-=i&-i)
is=0,rk-=query(root[i],1,n,pos),cnt0-=is;
for(int i=r;i;i-=i&-i)
is=0,rk+=query(root[i],1,n,pos),cnt0+=is;
return rk+(cnt0>0);
}
int rl[N],rr[N];
int frank(int l,int r,int k)//l到r排名为k的数
{
int ad,de;
for(int i=l-1;i;i-=i&-i) rl[i]=root[i];
for(int i=r;i;i-=i&-i) rr[i]=root[i];
int L=1,R=n;
while(L<R)
{
ad=de=0;
int Mid=L+R>>1;
for(int i=l-1;i;i-=i&-i) de+=sum[ls[rl[i]]];
for(int i=r;i;i-=i&-i) ad+=sum[ls[rr[i]]];
if(ad-de>=k)
{
R=Mid;
for(int i=l-1;i;i-=i&-i) rl[i]=ls[rl[i]];
for(int i=r;i;i-=i&-i) rr[i]=ls[rr[i]];
}
else
{
L=Mid+1;
k-=ad-de;
for(int i=l-1;i;i-=i&-i) rl[i]=rs[rl[i]];
for(int i=r;i;i-=i&-i) rr[i]=rs[rr[i]];
}
}
return dat[L];
}
void pre(int l,int r,int pos)
{
int rk=Rank(l,r,pos-1);
if(!rk) printf("%d\n",-inf);
else printf("%d\n",frank(l,r,rk));
}
void suc(int l,int r,int pos)
{
add(l,pos+1,1);
int rk=Rank(l,r,pos+1);
add(l,pos+1,-1);
if(rk==r+2-l) printf("%d\n",inf);
else printf("%d\n",frank(l,r,rk));
}
void init()
{
scanf("%d%d",&n_,&m);
for(int i=1;i<=n_;i++)
{
scanf("%d",&num[i].first);
num[i].second.first=i;
}
n0=n_;
for(int i=1;i<=m;i++)
{
scanf("%d",&op[i].opt);
if(op[i].opt==3)
scanf("%d%d",&op[i].l,&op[i].k);
else
scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].k);
if(op[i].opt!=2)
{
num[++n0].first=op[i].k;
num[n0].second.first=i+n_;
}
}
sort(num+1,num+1+n0);
num[0].first=inf;
for(int i=1;i<=n0;i++)
{
if(num[i].first!=num[i-1].first) ++n;
ss=n,dat[n]=num[i].first;
}
for(int i=1;i<=n0;i++)
{
if(sf<=n_) las[sf]=ss,add(sf,ss,1);
else op[sf-n_].k=ss;
}
}
void work()
{
for(int i=1;i<=m;i++)
{
if(op[i].opt==1)
{
add(op[i].l,op[i].k,1);
printf("%d\n",Rank(op[i].l,op[i].r,op[i].k));
add(op[i].l,op[i].k,-1);
}
else if(op[i].opt==2) printf("%d\n",frank(op[i].l,op[i].r,op[i].k));
else if(op[i].opt==3)
{
add(op[i].l,las[op[i].l],-1);
las[op[i].l]=op[i].k;
add(op[i].l,las[op[i].l],1);
}
else if(op[i].opt==4)
pre(op[i].l,op[i].r,op[i].k);
else
suc(op[i].l,op[i].r,op[i].k);
}
}
int main()
{
init();
work();
return 0;
}

2018.8.1

洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)的更多相关文章

  1. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  2. 洛谷 P3380 【【模板】二逼平衡树(树套树)】

    其实比想象中的好理解啊 所谓树套树,就是在一棵树的基础上,每一个节点再维护一棵树 说白了,就是为了实现自己想要的操作和优秀的时间复杂度,来人为的增加一些毒瘤数据结构来维护一些什么东西 比如说这道题 如 ...

  3. bzoj3196: Tyvj 1730 二逼平衡树 树套树

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...

  4. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  5. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

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

  6. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  7. 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

    线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...

  8. 【洛谷3865】 【模板】ST表(猫树)

    传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里

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

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

随机推荐

  1. JDK1.8改为JDK1.7过程

    电脑之前eclipse版本要求JDK1.8版本,现在要用jboss7.1做性能测试,目前仅支持JDK7.故需要降级. 网上有很多说把1.8删掉,这种做法我是不建议的,那么要用的时候呢?又得装回来多蛋疼 ...

  2. Windows运行机理——消息与消息队列

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 Windows程序设计时一种基于消息的时机驱动方式的设计模式,完全不同 ...

  3. OSG-OSG中的observer_ptr指针

    看array大神的CookBook后一些感想,在代码上添加了一些注释,也对源码做了一些研读,记录下学习的过程. CookBook中第一个例子就是observer_ptr指针,这个指针和它的名字一样,就 ...

  4. es6笔记4^_^function

    一.function默认参数 现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了. es5 function sayHello(name){ //传统的指定默认参 ...

  5. Java并发基础--ThreadLocal

    一.ThreadLocal定义 ThreadLocal是一个可以提供线程局部变量的类,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路,通过为每个线程提供一个独立的变量副本解决了变量 ...

  6. vue中如何实现pdf文件预览?

    今天产品提出一个优化的需求,就是之前我们做的图片展示就是一个img标签搞定,由于我们做的是海外后台管理系统,那边的人上传的文件时pdf格式,vue本事是不支持这种格式文件展示的,于是就google搜索 ...

  7. leetcode-帕斯卡三角形

    帕斯卡三角形 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行. 示例: 输入: 5 输出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4 ...

  8. 论文阅读之Joint cell segmentation and tracking using cell proposals

    论文提出了一种联合细胞分割和跟踪方法,利用细胞segmentation proposals创建有向无环图,然后在该图中迭代地找到最短路径,为单个细胞提供分割,跟踪和事件. 3. PROPOSAL GE ...

  9. Alpha冲刺——第一天

    Alpha第一天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  10. activity属性设置大全

    activity属性设置大全 android:allowTaskReparenting=["true" | "false"]         是否允许activ ...