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

题目描述

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

查询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. 使用union

    QUERY: explain extended ) TRACE: { "steps": [ { "join_preparation": { "sele ...

  2. C# 组装XML传给webserver+XML 返回获取多个xml,根据多个XML 返回dataset类型

    大致流程介绍: 传值给 webserver+XML ,得到webserver+XML多个返回值,组装成dataset形式返回 首先创建所需要的类型 DataSet ds = new DataSet() ...

  3. Visual Studio 起始页中不显示最近使用的项目的解决办法

    将 HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/NoRecentDocsHistory的 ...

  4. oracle的数据对象

    oracle的数据对象包括表.视图.约束.序列.索引.函数.存储过程.包和触发器等. 这里主要介绍视图.序列.索引.触发器.存储过程 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以 ...

  5. 阿里云ECS下CentOS7.4 yum安装Python3.6环境

    一.安装EPEL和IUS软件源 二.安装Python3.6 三.创建python3软链接连接符 四.安装pip3 五.创建pip3链接符 六.进行验证是否安装成功 一.安装EPEL和IUS软件源 yu ...

  6. lintcode174 删除链表中倒数第n个节点

    删除链表中倒数第n个节点   给定一个链表,删除链表中倒数第n个节点,返回链表的头节点. 注意事项 链表中的节点个数大于等于n 您在真实的面试中是否遇到过这个题? Yes 样例 给出链表1->2 ...

  7. 【CQOI 2007】 余数求和

    题目描述 给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如G(10, 5)=5 ...

  8. [转载]启动tomcat时,一直卡在Deploying web application directory这块的解决方案

    转载:https://www.cnblogs.com/mycifeng/p/6972446.html 本来今天正常往服务器上扔一个tomcat 部署一个项目的, 最后再启动tomcat 的时候 发现项 ...

  9. Sharepoint 2013与Sharepoint 2016的功能对比

    开发人员功能 SharePoint Foundation 2013 SharePoint Server 2013 Standard CAL SharePoint Server 2013 Enterpr ...

  10. geth账户密码

    xiaocong geth账户密码 123 {d6abe909013d8da914ae2a08c9b58e7b76601b39} 账户密码 123456 0x4A7F15104F54dB3214D2F ...