[学习笔记]树套树 线段树套Splay
今天调了一个早上哈哈哈,不过因为\(Splay\),常数比较大
洛谷的评测记录:
\(Code\ Below:\)
#include <bits/stdc++.h>
#define ll long long
#define mid (l+r>>1)
using namespace std;
const int maxn=4000010;
const int inf=2147483647;
int n,m,sz,ans,Max;
int a[maxn],ch[maxn][2],fa[maxn],siz[maxn],cnt[maxn],key[maxn],rt[maxn];
inline void splayclear(int x){
fa[x]=ch[x][0]=ch[x][1]=siz[x]=cnt[x]=key[x]=0;
}
inline bool get(int x){
return ch[fa[x]][1]==x;
}
inline void update(int x){
siz[x]=(ch[x][0]?siz[ch[x][0]]:0)+(ch[x][1]?siz[ch[x][1]]:0)+cnt[x];
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=get(x);
ch[y][k]=ch[x][k^1];fa[ch[y][k]]=y;
ch[x][k^1]=y;fa[y]=x;fa[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
update(y);update(x);
}
inline void splay(int i,int x,int top){
for(int y,z;fa[x]!=top;rotate(x)){
y=fa[x],z=fa[y];
if(z!=top) rotate(get(x)==get(y)?y:x);
}
if(!top) rt[i]=x;
}
inline void splayinsert(int i,int val){
int x=rt[i],y;
if(!rt[i]){
rt[i]=x=++sz;fa[x]=ch[x][0]=ch[x][1]=0;
key[x]=val;siz[x]=cnt[x]=1;return;
}
while(1){
if(key[x]==val){cnt[x]++;update(y);break;}
y=x;x=ch[x][key[x]<val];
if(x==0){
x=++sz;key[x]=val;siz[x]=cnt[x]=1;
ch[y][key[y]<val]=x;fa[x]=y;
update(y);break;
}
}
splay(i,x,0);
}
inline int splayrank(int i,int val){
int x=rt[i],ret=0;
while(x>0){
if(val<key[x]) x=ch[x][0];
else {
ret+=(ch[x][0]?siz[ch[x][0]]:0);
if(val==key[x]) return ret;
ret+=cnt[x];x=ch[x][1];
}
}
return ret;
}
inline int splayfind(int i,int val){
int x=rt[i];
while(x>0){
if(val==key[x]){splay(i,x,0);return x;}
x=ch[x][key[x]<val];
}
}
inline int splaypre(int i){int x=ch[rt[i]][0];while(ch[x][1])x=ch[x][1];return x;}
inline int splaysuc(int i){int x=ch[rt[i]][1];while(ch[x][0])x=ch[x][0];return x;}
inline void splaydel(int i,int val){
int x=splayfind(i,val),y=rt[i];
if(cnt[x]>1){cnt[x]--;update(x);return;}
if(!ch[x][0]&&!ch[x][1]){splayclear(rt[i]);rt[i]=0;return;}
if(!ch[x][0]){y=ch[x][1];rt[i]=y;fa[y]=0;return;}
if(!ch[x][1]){y=ch[x][0];rt[i]=y;fa[y]=0;return;}
splay(i,splaypre(i),0);
ch[rt[i]][1]=ch[y][1];fa[ch[y][1]]=rt[i];
splayclear(y);update(rt[i]);
}
inline int splaygetpre(int i,int val){
int x=rt[i];
while(x>0){
if(val<=key[x]) x=ch[x][0];
else {
if(key[x]>ans) ans=key[x];
x=ch[x][1];
}
}
return ans;
}
inline int splaygetsuc(int i,int val){
int x=rt[i];
while(x>0){
if(val>=key[x]) x=ch[x][1];
else {
if(key[x]<ans) ans=key[x];
x=ch[x][0];
}
}
return ans;
}
inline void seginsert(int l,int r,int rt,int x,int val){
splayinsert(rt,val);
if(l == r) return;
if(x <= mid) seginsert(l,mid,rt<<1,x,val);
else seginsert(mid+1,r,rt<<1|1,x,val);
}
inline void segrank(int L,int R,int val,int l,int r,int rt){
if(L <= l && r <= R){ans+=splayrank(rt,val);return;}
if(L <= mid) segrank(L,R,val,l,mid,rt<<1);
if(R > mid) segrank(L,R,val,mid+1,r,rt<<1|1);
}
inline void segchange(int l,int r,int rt,int x,int val){
splaydel(rt,a[x]);splayinsert(rt,val);
if(l == r){a[x]=val;return;}
if(x <= mid) segchange(l,mid,rt<<1,x,val);
else segchange(mid+1,r,rt<<1|1,x,val);
}
inline void segpre(int L,int R,int val,int l,int r,int rt){
if(L <= l && r <= R){ans=max(ans,splaygetpre(rt,val));return;}
if(L <= mid) segpre(L,R,val,l,mid,rt<<1);
if(R > mid) segpre(L,R,val,mid+1,r,rt<<1|1);
}
inline void segsuc(int L,int R,int val,int l,int r,int rt){
if(L <= l && r <= R){ans=min(ans,splaygetsuc(rt,val));return;}
if(L <= mid) segsuc(L,R,val,l,mid,rt<<1);
if(R > mid) segsuc(L,R,val,mid+1,r,rt<<1|1);
}
inline int getkth(int L,int R,int k){
int l=0,r=Max+1,Mid;
while(l<r){
Mid=l+r>>1;ans=0;
segrank(L,R,Mid,1,n,1);
if(ans<k) l=Mid+1;
else r=Mid;
}
return l-1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
seginsert(1,n,1,i,a[i]);
Max=max(Max,a[i]);
}
int opt,l,r,val;
while(m--){
scanf("%d%d%d",&opt,&l,&r);
switch(opt){
case 1:scanf("%d",&val);ans=0;segrank(l,r,val,1,n,1);printf("%d\n",ans+1);break;
case 2:scanf("%d",&val);printf("%d\n",getkth(l,r,val));break;
case 3:segchange(1,n,1,l,r);break;
case 4:scanf("%d",&val);ans=-inf;segpre(l,r,val,1,n,1);printf("%d\n",ans);break;
case 5:scanf("%d",&val);ans=inf;segsuc(l,r,val,1,n,1);printf("%d\n",ans);break;
}
}
return 0;
}
[学习笔记]树套树 线段树套Splay的更多相关文章
- ACM学习笔记:可持久化线段树
title : 可持久化线段树 date : 2021-8-18 tags : 数据结构,ACM 可持久化线段树 可以用来解决线段树存储历史状态的问题. 我们在进行单点修改后,线段树只有logn个(一 ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
- BZOJ 3218(a + b Problem-二分图套值域线段树)
出这题的人是怎么想出来的…… 言归正传,这题是二分图套值域线段树. 首先经过 @Vfleaking的神奇建图后,把图拆成二分图, 不妨利用有向图最小割的性质建图(以前我一直以为最小割和边的方向无关,可 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- 树状数组 && 线段树应用 -- 求逆序数
参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...
- 差分+树状数组 线段树【P2357】 守墓人
题目描述-->p2357 守墓人 敲了一遍线段树,水过. 树状数组分析 主要思路: 差分 简单介绍一下差分(详细概念太麻烦,看下面. 给定一个数组 7 8 6 5 1 8 18 20 35 // ...
随机推荐
- 使用yarn 安装 Vue-DevTools
1. 从 github 下载 vuejs/vue-devtools https://github.com/vuejs/vue-devtools/archive/dev.zip 2.安装yarn 及 编 ...
- springMVC学习一 工作机制
springMVC下面的四大组件: (1)DispatcherServlet : 前端控制器,接收所有请求 ,并把请求路径和请求参数解析出来,本质是一个servlet在web.xml中配置 (如果配置 ...
- Mac下Maven安装与配置
Mac下Maven安装与配置 下载maven http://maven.apache.org/download.cgi main->download菜单下的Files 下载后解压在Documen ...
- Windows AD域管理软件是什么?
Windows AD域管理软件是什么? ADManager Plus是一个简单易用的Windows AD域管理工具,帮助域管理员简化日常的管理工作.通过直观友好的操作界面,可以执行复杂的管理操作,比如 ...
- 70.app上架被拒(info.plist定位参数配置)
问题一: Your app declares support for location in the UIBackgroundModes key in your Info.plist file but ...
- 前端之html的常用标签2和css基本使用
一 列表标签 ul标签:无序列表 ol标签:有序列表 li标签:写在ul和ol标签里面的 dl标签:定义列表 dt标签和dd标签:都写在dl里面的 <!DOCTYPE html> < ...
- 2018.10.27 洛谷P2915奶牛混合起来Mixed Up Cows(状压dp)
传送门 状压dp入门题. 按照题意建一个图. 要求的就是合法的链的总数. 直接f[i][j]f[i][j]f[i][j]表示当前状态为jjj,下一位要跟iii连起来的方案数. 然后从没被选并且跟iii ...
- ac自动机板子
hdu2222 #include<bits/stdc++.h> #define ll long long #define M 500005 using namespace std; int ...
- oss 上传文件夹-cloud2-泽优软件
说明: 1. 修复同时上传多个文件夹崩溃的问题. 2. 修复阿里云(OSS)特殊文件名称无法上传的问题. 3. 文件夹MD5提供配置项(默认关闭).
- 队列<一>
这里用的递归法,采用两种版本,一种是C语言,一种是C++:但是,用C语言没有“引用”,所以采用的是指向指针的指针:而C++具备“引用”,所以直接用&引用,简洁: 先看C++的代码: BiTre ...