传送门

题意

给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种:

  1. 查询 $ k $ 在区间 $ [l,r] $ 内的排名
  2. 查询区间 $ [l,r] $ 内排名为 $ k $ 的值
  3. 将 $ a[p] $ 修改为 $ k $
  4. 查询 $ k $ 在区间 $ [l,r] $ 内的前驱(前驱定义为小于 $ k $ ,且最大的数)
  5. 查询 $ k $ 在区间 $ [l,r] $ 内的后继(后继定义为大于 $ k $ ,且最小的数)

题解

线段树套splay。

先将 $ n $ 个数插入线段树:对于每个 $ a[i] $,将线段树上到位置 $ i $ 的叶子节点的路径上的所有splay插入元素 $ a[i] $ 。

操作1:区间 $ [l,r] $ 在线段树上对应了若干棵splay,将这些splay中小于 $ k $ 的元素个数累加,记为 $ sum $ ,$ sum+1 $ 即为答案。

操作2:二分这个元素的值,然后进行操作1得到当前rank,对应地调整答案。

操作3:将线段树上到位置 $ p $ 的叶子节点的路径上的所有splay删除 $ a[p] $ ,再插入 $ k $ ,然后更新 $ a[p] = k $ 。

操作4:将区间 $ [l,r] $ 对应的所有splay中查询到的 $ k $ 的前驱取 $ max $ 即可。

操作5:将区间 $ [l,r] $ 对应的所有splay中查询到的 $ k $ 的后继取 $ min $ 即可。

最后,纪念一下我用pbds加map封装的的假splay......QAQ

还有就是因为b站g++版本太老,null_type会CE,要改成null_mapped_type

AC Code

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define MAX_N 50005
#define MAX_V 200005
#define INF 2147483647 using namespace std;
using namespace __gnu_pbds; typedef tree<pair<int,int>,null_mapped_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update> Tree;
typedef Tree::iterator git; struct Splay
{
Tree t;
map<int,int> mp;
void ins(int x)
{
t.insert(make_pair(x,mp[x]=mp[x]+1));
}
void del(int x)
{
t.erase(make_pair(x,mp[x])),mp[x]=mp[x]-1;
}
int pre(int x)
{
if(t.empty()) return -INF;
git it=t.lower_bound(make_pair(x,0));
if(it==t.begin()) return -INF;
return (--it)->first;
}
int suc(int x)
{
if(t.empty()) return INF;
git it=t.upper_bound(make_pair(x,INF));
if(it==t.end()) return INF;
return it->first;
}
int kth(int x)
{
return t.find_by_order(x-1)->first;
}
int rk(int x)
{
return t.order_of_key(make_pair(x,1))+1;
}
}; int n,m;
int a[MAX_N];
Splay t[MAX_V]; void ins(int p,int k,int l,int r,int x)
{
t[k].ins(x);
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) ins(p,k*2+1,l,mid,x);
else ins(p,k*2+2,mid+1,r,x);
} int getrk(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b) return t[k].rk(x)-1;
int mid=(l+r)>>1,ans=0;
if(a<=mid) ans+=getrk(a,b,k*2+1,l,mid,x);
if(b>mid) ans+=getrk(a,b,k*2+2,mid+1,r,x);
return ans;
} int getx(int a,int b,int k)
{
int l=0,r=INF;
while(r-l>1)
{
int mid=(l+r)>>1;
if(getrk(a,b,0,1,n,mid)<=k-1) l=mid;
else r=mid;
}
return l;
} void upd(int p,int k,int l,int r,int x)
{
t[k].del(a[p]),t[k].ins(x);
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) upd(p,k*2+1,l,mid,x);
else upd(p,k*2+2,mid+1,r,x);
} int getpre(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b) return t[k].pre(x);
int mid=(l+r)>>1,ans=-INF;
if(a<=mid) ans=max(ans,getpre(a,b,k*2+1,l,mid,x));
if(b>mid) ans=max(ans,getpre(a,b,k*2+2,mid+1,r,x));
return ans;
} int getsuc(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b) return t[k].suc(x);
int mid=(l+r)>>1,ans=INF;
if(a<=mid) ans=min(ans,getsuc(a,b,k*2+1,l,mid,x));
if(b>mid) ans=min(ans,getsuc(a,b,k*2+2,mid+1,r,x));
return ans;
} int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),ins(i,0,1,n,a[i]);
int opt,l,r,k,p;
while(m--)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",getrk(l,r,0,1,n,k)+1);
}
if(opt==2)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",getx(l,r,k));
}
if(opt==3)
{
scanf("%d%d",&p,&k);
upd(p,0,1,n,k),a[p]=k;
}
if(opt==4)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",getpre(l,r,0,1,n,k));
}
if(opt==5)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",getsuc(l,r,0,1,n,k));
}
}
}

BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay的更多相关文章

  1. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

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

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

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

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

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

  4. [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

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

  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. BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

    这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...

  8. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

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

  9. BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 http://hzwer.com/2734.html 线段树套treap,似乎splay也可以 ...

随机推荐

  1. FFMPEG推流到RTMP服务器命令 - weixin_37897683的博客 - CSDN博客 https://blog.csdn.net/weixin_37897683/article/details/81225228

    FFMPEG推流到RTMP服务器命令 - weixin_37897683的博客 - CSDN博客 https://blog.csdn.net/weixin_37897683/article/detai ...

  2. 分布式计算 要不要把写日志独立成一个Server Remote Procedure Call Protocol

    w https://en.wikipedia.org/wiki/Remote_procedure_call In distributed computing a remote procedure ca ...

  3. 使用jQuery操作Cookies

    转载自: https://www.cnblogs.com/yonge/articles/2698106.html Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的 ...

  4. 原!!mysql,几十万条数据中随机抽取1万以内的数据

    想了几种方法: 1.将所有符合条件的对象集合都查出来,在代码里做随机. 2.先查出所有符合条件的id,再代码随机需要抽查数量的id,再 到数据库 中 in. 3.利用order by rand() l ...

  5. django博客项目4:博客首页视图(1)

    Web 应用的交互过程其实就是 HTTP 请求与响应的过程.无论是在 PC 端还是移动端,我们通常使用浏览器来上网,上网流程大致来说是这样的: 我们打开浏览器,在地址栏输入想访问的网址,比如 http ...

  6. Perceptual Generative Adversarial Networks for Small Object Detection

    Perceptual Generative Adversarial Networks for Small Object Detection 感知生成对抗网络用于目标检测 论文链接:https://ar ...

  7. Android图片加载框架Picasso最全使用教程4

    通过前几篇的学习,我们已经对Picasso的加载图片的用法有了很深的了解,接下来我们开始分析Picasso为我们提供的其他高级功能及内存分析,Let’sGo ! Picasso进行图片的旋转(Rota ...

  8. Python Network Programming

    @1: 同步网络编程(也就是阻塞方式) 同步网络编程一次只能连接一个客户端. Server端: import socket def debugPrint(name, value): print(&qu ...

  9. Django——请求生命周期

    视图层之视图函数(views) 一个视图函数,简称视图,他可以接受Web请求,并且必须返回一个Web响应,响应内容可以是一个HTML内容,一张图片,一个404错误,一个文档等等,都可以称为web为你响 ...

  10. go——反射

    反射(reflect)让我们能在运行期探知对象地类型信息和内存结构,这从一定程度上弥补了静态语言在动态行为上地不足.和C数据结构一样,Go对象头部并没有类型指针,通过其自身是无法在运行期获知任何类型相 ...