浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html

浅谈\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2028

此题的线段树写法:https://www.cnblogs.com/AKMer/p/9948789.html

我如果要插入一个新的区间\([l,r]\),会被这个预约冲掉的区间显然满足\(st\leqslant r\)且\(ed\geqslant l\)。对于这样的预约是连续的一段,于是我们就可以通过区间删除来达到踢出预约的效果了。那么怎么找这连续的一段区间呢?

对于\(splay\)

将结束时间严格小于\(l\)的预约旋到根,将起始时间严格大于\(r\)的预约旋到根的右儿子。那么根的右儿子的左子树里所有的预约就都是会被当前预约冲掉的预约,直接全部删掉就行了。

对于\(fhq\)_\(treap\)

将整个树分成三部分,第一部分满足所有结点结束时间严格小于\(l\),第三部分满足所有结点起始时间严格大于\(l\),然后直接把第二部分换成代表新的预约的结点\(merge\)起来就行了。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(n)\)

\(splay\)版代码如下:

#include <cstdio>
using namespace std; const int maxn=2e5+5,inf=2e9; int n;
char s[5]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct Splay {
int tot,root;
int fa[maxn],son[maxn][2];
int val[maxn][2],siz[maxn]; int newnode(int l,int r) {
siz[++tot]=1;
val[tot][0]=l,val[tot][1]=r;
return tot;
} int t(int u) {
return son[fa[u]][1]==u;
} void update(int u) {
siz[u]=siz[son[u][0]]+1+siz[son[u][1]];
} void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;update(f);update(u);
} void splay(int goal,int u) {
int tmp=fa[goal];
while(fa[u]!=tmp) {
if(fa[fa[u]]!=tmp) {
if(t(fa[u])==t(u))rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
if(!tmp)root=u;
} int find(int opt,int v) {
int u=root;
while(val[u][opt]!=v) {
if(val[u][opt]<v) {if(son[u][1])u=son[u][1];else break;}
if(val[u][opt]>v) {if(son[u][0])u=son[u][0];else break;}
}
return u;
} int get_pre(int v) {
int u=find(1,v);splay(root,u);
if(val[u][1]<v)return u;
u=son[u][0];
while(son[u][1])u=son[u][1];
return u;
} int get_suc(int v) {
int u=find(0,v);splay(root,u);
if(val[u][0]>v)return u;
u=son[u][1];
while(son[u][0])u=son[u][0];
return u;
} void ins(int l,int r) {
int u=get_pre(l),v=get_suc(r);
splay(root,u);splay(son[root][1],v);
son[v][0]=newnode(l,r);fa[tot]=v;
update(v);update(u);
} void prepare() {
int a=newnode(-inf,-inf),b=newnode(inf,inf);
son[a][1]=b;fa[b]=a;update(a);root=a;
}
}T; int main() {
T.prepare();
n=read();
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
if(s[1]=='B')printf("%d\n",T.siz[T.root]-2);
else {
int l=read(),r=read();
int tmp=T.siz[T.root];
T.ins(l,r);
printf("%d\n",tmp-(T.siz[T.root]-1));
}
}
return 0;
}

\(fhq\)_\(treap\)版代码如下:

#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii; const int maxn=2e5+5; int n;
char s[5]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct fhq_treap {
int tot,root;
int fix[maxn],son[maxn][2];
int siz[maxn],val[maxn][2]; int newnode(int l,int r) {
fix[++tot]=rand();
val[tot][0]=l,val[tot][1]=r;
siz[tot]=1;return tot;
} void update(int u) {
siz[u]=siz[son[u][0]]+1+siz[son[u][1]];
} int find(int u,int opt,int v,int bo) {
if(!u)return 0;
int ans=0;
if(val[u][opt]>v)ans=find(son[u][0],opt,v,bo);
else if(val[u][opt]==v)return siz[son[u][0]]+bo;
else ans=siz[son[u][0]]+1+find(son[u][1],opt,v,bo);
return ans;
} pii split(int u,int rk) {
if(!rk)return make_pair(0,u);
if(rk==siz[u])return make_pair(u,0);
if(siz[son[u][0]]>=rk) {
pii tmp=split(son[u][0],rk);
son[u][0]=tmp.second,update(u);
return make_pair(tmp.first,u);
}
else {
pii tmp=split(son[u][1],rk-siz[son[u][0]]-1);
son[u][1]=tmp.first,update(u);
return make_pair(u,tmp.second);
}
} int merge(int a,int b) {
if(!a||!b)return a+b;
if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
else return son[b][0]=merge(a,son[b][0]),update(b),b;
} int ins(int l,int r) {
int rk1=find(root,0,r,1),rk2=find(root,1,l,0);
pii tmp1=split(root,rk1),tmp2=split(tmp1.first,rk2);
root=merge(merge(tmp2.first,newnode(l,r)),tmp1.second);
return siz[tmp2.second];
}
}T; int main() {
srand(time(0));n=read();
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
if(s[1]=='B')printf("%d\n",T.siz[T.root]);
else {
int l=read(),r=read();
printf("%d\n",T.ins(l,r));
}
}
return 0;
}

BZOJ2028:[SHOI2009]会场预约(平衡树版)的更多相关文章

  1. BZOJ2028: [SHOI2009]会场预约(set)

    Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 425  Solved: 213[Submit][Status][Discuss] Description ...

  2. 2021.12.08 [SHOI2009]会场预约(平衡树游码表)

    2021.12.08 [SHOI2009]会场预约(平衡树游码表) https://www.luogu.com.cn/problem/P2161 题意: 你需要维护一个 在数轴上的线段 的集合 \(S ...

  3. [LuoguP2161[ [SHOI2009]会场预约 (splay)

    题面 传送门:https://www.luogu.org/problemnew/show/P2161 Solution splay 的确有线段树/树状数组的做法,但我做的时候脑残没想到 我们可以考虑写 ...

  4. 【题解】P2161[SHOI2009]会场预约(set)

    [题解][P2161 SHOI2009]会场预约 题目很像[[题解]APIO2009]会议中心 \(set\)大法好啊! 然后我们有个小\(trick\)(炒鸡帅),就是如何优雅地判断线段交? str ...

  5. SHOI 2009 会场预约 平衡树 STL练习

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...

  6. [SHOI2009] 会场预约 - Treap

    Description PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也 ...

  7. P2161 [SHOI2009]会场预约

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...

  8. P2161 [SHOI2009]会场预约 (线段树:线段树上的不重复覆盖数)

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...

  9. P2161 [SHOI2009]会场预约[线段树/树状数组+二分/STL]

    题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...

随机推荐

  1. BZOJ 2005 NOI2010 能量採集 数论+容斥原理

    题目大意:给定n和m.求Σ(1<=i<=n)Σ(1<=j<=m)GCD(i,j)*2-1 i和j的限制不同,传统的线性筛法失效了.这里我们考虑容斥原理 令f[x]为GCD(i, ...

  2. SQL注入基础入门

    一般的WEB架构 SQL注入成因: 用户开启浏览器并连接http://www.xxx.com.位于逻辑层的Web服务器从文件系统中加载脚本将其传递给脚本引擎,脚本引擎负责解析并执行脚本. 脚本使用数据 ...

  3. [Linux] 网络

    如何在网络中标识一台计算机 IP 多个程序如何不冲突 通信端口 不同的计算机如何通信 协议 IP A类:0+7位网络号+24位主机号,可用网络2^7-2个,每个网络可容纳2^24-2个主机 B类:10 ...

  4. 如何创建虚拟硬盘 + os 读取硬盘参数代码

    [0]README 0.1) 本文旨在演示如何利用 bximage 创建虚拟硬盘: 0.2) 利用 os 读取硬盘参数, source code from orange's implemention ...

  5. struts2_6_多个struts配置文件的应用

    在大部分应用里,随着应用规模的添加,系统中Action的数量也会大量添加.导致struts.xml配置文件变的很臃肿,为了避免struts.xml文件过于庞大.臃肿,提高struts.xml文件的可读 ...

  6. python 基础 6.2 raise 关键字使用

    一. raise 关键字    raise 用来触发异常    语法如下:     raise[Exception [,args [,traceback]]]     语句中Exception 是异常 ...

  7. 【BZOJ3451】Tyvj1953 Normal 点分治+FFT+期望

    [BZOJ3451]Tyvj1953 Normal Description 某天WJMZBMR学习了一个神奇的算法:树的点分治!这个算法的核心是这样的:消耗时间=0Solve(树 a) 消耗时间 += ...

  8. consistence availability partition tolerance quit

    理论证明

  9. 【题解】P3162CQOI2012组装

    [题解][CQOI2012]组装 考虑化为代数的形式,序列\(\left[a_i \right]\)表示选取的\(i\)种类仓库的坐标. \(ans=\Sigma(a_i-x)^2,(*)\),展开: ...

  10. 调用jersey发布的接口webservice,通过HttpPost传递文件

    项目媒体文件之前都是上传到七牛云处理,现在客户为了安全和私密性,准备将移动端拍摄的图片和视频传递到文件服务器,所以就想办法能不能在服务器端发布一个WebService,供移动端调用.刚好之前做的接口都 ...