BZOJ3196:二逼平衡树(线段树套Splay)

时间:2022-02-18 14:05:31

Description

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

Input

第一行两个数 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的后继

Output

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

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数

Solution

板子题也没啥好写的……找个好看点的板子比如我的抄抄吧

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#define N (3000000+100)
using namespace std; int Root[N],sz,Father[N],Son[N][];
int Cnt[N],Val[N],Size[N];
int n,m,a[N],Ans,maxn; inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} struct Splay_Tree
{
int Get(int x) { return Son[Father[x]][]==x; }
void Update(int x) { Size[x]=Size[Son[x][]]+Size[Son[x][]]+Cnt[x]; }
void New(int x) { ++sz; Size[sz]=; Val[sz]=x; Cnt[sz]=; }
void Clear(int x) { Size[x]=Father[x]=Son[x][]=Son[x][]=Cnt[x]=Val[x]=; }
int Pre(int Root) { int now=Son[Root][]; while (Son[now][]) now=Son[now][]; return now; }
int Next(int Root) { int now=Son[Root][]; while (Son[now][]) now=Son[now][]; return now; } void Rotate(int x)
{
int wh=Get(x),fa=Father[x],fafa=Father[fa];
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Father[fa]=x; Son[fa][wh]=Son[x][wh^];
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Father[x]=fafa; Son[x][wh^]=fa;
Update(fa); Update(x);
}
void Splay(int &Root,int x)
{
for (int fa;fa=Father[x];Rotate(x))
if (Father[fa])
Rotate(Get(fa)==Get(x)?fa:x);
Root=x;
}
int Findx(int &Root,int x)
{
int now=Root;
while ()
if (x<=Size[Son[now][]])
now=Son[now][];
else
{
if (x<=Cnt[now])
{
Splay(Root,now);
return now;
}
x-=Cnt[now];
now=Son[now][];
}
}
int Find(int &Root,int x)
{
int now=Root,ans=;
while ()
{
if (!now) return ans;
if (x<Val[now])
now=Son[now][];
else
{
ans+=Size[Son[now][]];
if (Val[now]==x)
{
Splay(Root,now);
return ans;
}
ans+=Cnt[now];
now=Son[now][];
}
}
}
void Insert(int &Root,int x)
{
if (!Root) { New(x); Root=sz; return; }
int now=Root,fa=;
while ()
{
if (x==Val[now]) { ++Cnt[now]; Update(now); Splay(Root,now); return; }
fa=now; now=Son[now][x>Val[now]];
if (now==){ New(x); Father[sz]=fa; Son[fa][x>Val[fa]]=sz; Splay(Root,sz); return; }
}
}
void Delete(int &Root,int x)
{
Find(Root,x);
if (Cnt[Root]>) { Cnt[Root]--; Update(Root); return; }
if (!Son[Root][] && !Son[Root][]) { Clear(Root); Root=; return; }
if (!Son[Root][]) { Root=Son[Root][]; Clear(Father[Root]); Father[Root]=; return; }
if (!Son[Root][]) { Root=Son[Root][]; Clear(Father[Root]); Father[Root]=; return; } int oldroot=Root,pre=Pre(Root);
Splay(Root,pre);
Son[Root][]=Son[oldroot][];
Father[Son[oldroot][]]=Root;
Clear(oldroot);
Update(Root);
}
}; struct Segt_Tree
{
Splay_Tree Splay[];
void Get_rank(int node,int l,int r,int l1,int r1,int k)
{
if (l>r1 || r<l1) return;
if (l1<=l && r<=r1)
{
Ans+=Splay[node].Find(Root[node],k);
return;
}
int mid=(l+r)>>;
Get_rank(node<<,l,mid,l1,r1,k);
Get_rank(node<<|,mid+,r,l1,r1,k);
}
void Update(int node,int l,int r,int x,int k)
{
Splay[node].Delete(Root[node],a[x]);
Splay[node].Insert(Root[node],k);
if (l==r) return;
int mid=(l+r)>>;
if (x<=mid) Update(node<<,l,mid,x,k);
else Update(node<<|,mid+,r,x,k);
}
void Pre(int node,int l,int r,int l1,int r1,int k)
{
if (l>r1 || r<l1) return;
if (l1<=l && r<=r1)
{
Splay[node].Insert(Root[node],k);
int pre=Splay[node].Pre(Root[node]);
Ans=max(Ans,Val[pre]);
Splay[node].Delete(Root[node],k);
return;
}
int mid=(l+r)>>;
Pre(node<<,l,mid,l1,r1,k);
Pre(node<<|,mid+,r,l1,r1,k);
}
void Next(int node,int l,int r,int l1,int r1,int k)
{
if (l>r1 || r<l1) return;
if (l1<=l && r<=r1)
{
Splay[node].Insert(Root[node],k);
int next=Splay[node].Next(Root[node]);
Ans=min(Ans,next==?0x7fffffff:Val[next]);
Splay[node].Delete(Root[node],k);
return;
}
int mid=(l+r)>>;
Next(node<<,l,mid,l1,r1,k);
Next(node<<|,mid+,r,l1,r1,k);
}
void Ins(int node,int l,int r,int x,int k)
{
Splay[node].Insert(Root[node],k);
if (l==r) return;
int mid=(l+r)>>;
if (x<=mid) Ins(node<<,l,mid,x,k);
else Ins(node<<|,mid+,r,x,k);
}
}T; int main()
{
n=read(),m=read();
for (int i=; i<=n; ++i)
a[i]=read(),maxn=max(maxn,a[i]),T.Ins(,,n,i,a[i]);
int opt,l,r,k,pos;
for (int i=; i<=m; ++i)
{
opt=read();
switch(opt)
{
case :
{
l=read(),r=read(),k=read();
Ans=;
T.Get_rank(,,n,l,r,k);
printf("%d\n",Ans+);
break;
}
case :
{
l=read(),r=read(),k=read();
int L=,R=maxn;
while (L<R)
{
int mid=(L+R)>>;
Ans=;
T.Get_rank(,,n,l,r,mid);
if (Ans<k) L=mid+;
else R=mid;
}
printf("%d\n",L-);
break;
}
case :
{
pos=read(),k=read();
T.Update(,,n,pos,k);
a[pos]=k;
maxn=max(maxn,k);
break;
}
case :
{
l=read(),r=read(),k=read();
Ans=;
T.Pre(,,n,l,r,k);
printf("%d\n",Ans);
break;
}
case :
{
l=read(),r=read(),k=read();
Ans=0x7fffffff;
T.Next(,,n,l,r,k);
printf("%d\n",Ans);
break;
}
}
}
}

BZOJ3196:二逼平衡树(线段树套Splay)的更多相关文章

  1. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  2. BZOJ3196二逼平衡树——线段树套平衡树(treap)

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

  3. bzoj3196 二逼平衡树——线段树套平衡树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 人生中第一棵树套树! 写了一个晚上,成功卡时 9000ms+ 过了! 很要注意数组的大 ...

  4. bzoj 3196 &amp&semi;&amp&semi; luogu 3380 JoyOI 1730 二逼平衡树 &lpar;线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  5. BZOJ - 3196 Tyvj 1730 二逼平衡树 &lpar;线段树套treap&rpar;

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  6. &lbrack;bzoj3196&rsqb;Tyvj 1730 二逼平衡树——线段树套平衡树

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

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

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

  8. bzoj 3196二逼平衡树 线段树套平衡树

    比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细) //By BLADEVIL ...

  9. &lbrack;bzoj3196&rsqb;&lbrack;Tyvj 1730&rsqb;&lbrack;二逼平衡树&rsqb; &lpar;线段树套treap&rpar;

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

随机推荐

  1. js sort&lpar;&rpar; reverse&lpar;&rpar;

    数组中存在的两个方法:sort()和reverse() 直接用sort(),如下: ,,,,,,,,,,,]; console.log(array.sort());ps:[0, 1, 2, 2, 29 ...

  2. Linux 常用命令集合

    1. 常用命令 ls  显示当前目录下的文件和文件夹: -ltr 按时间顺序显示文件和文件夹的详细信息,不带参数的时候 只显示文件夹和文件. vi  打开文件的内容 tar -cvf file.tar ...

  3. System&period;BadImageFormatException&colon; 未能加载文件或程序集&quot&semi;&quot&semi;或它的某一个依赖项。试图加载格式不正确的程序。

    解决方法: 1.更改程序集的生成目标平台为[Any CPU],或者针对平台进行编译. 项目右键->[属性]->[生成]->[生成目标平台] 2.尝试一下修改线程池设置为32位支持.

  4. C&num;(类)

    一.String类 string s = " abCDefgb ";int a = s.Length;//获取长度 Console.WriteLine(s.Length); Con ...

  5. 南阳理工oj88--汉诺塔(一)

    题目链接.http://acm.nyist.net/JudgeOnline/problem.php?pid=88 #include <stdio.h> /* //测试一下49999和500 ...

  6. &lbrack;Oracle&rsqb; - 性能优化工具(5) - AWRSQL

    在AWR中定位到问题SQL语句后想要了解该SQL statement的详细运行计划,于是就用AWR报告中得到的SQL ID去V$SQL等几个动态性能视图中查询,但发现V$SQL或V$SQL_PLAN视 ...

  7. VisualStudio2013内置SQLServer入门

    最近做项目老大要求用到sqlserver,但是这项目的数据库只是本地演示用并不复杂,于是决定试试VisualStudio2013内置的SQLServer.对于这个东西的了解并没有多少,然后项目初学习的 ...

  8. 最详细的 HTTPS 科普扫盲帖

    为什么需要https HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号,密码, ...

  9. Polygenic score

    We estimate the maximum prediction accuracy for the risk of Alzheimer's disease based on disease pre ...

  10. &lbrack;转&rsqb;用 Jsp 的 Session 机制编写的购物车程序

    一.构建的商品类 //写一个Goods类,并定义商品的各个属性,返回商品属性的方法,以及商品对象进行比较的方法//Goods.java package com.viita.Shop; public c ...