浅谈\(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;
}

最新文章

  1. javascript 获取滚动条高度+常用js页面宽度与高度
  2. 如何在openresty里解析域名
  3. Android引用项目出现ClassNotFoundException
  4. C#--静态函数成员
  5. Oracle to_char()函数的使用细则
  6. NOI题库分治算法刷题记录
  7. 解决HttpServletResponse输出的中文乱码问题
  8. BZOJ3836 : [Poi2014]Tourism
  9. linux第12天 线程
  10. 设置AD用户属性
  11. 【概率】BZOJ 3450:Tyvj1952 Easy
  12. NicEdit - WYSIWYG Content Editor, Inline Rich Text Application
  13. tabbar动画切换
  14. 数据结构 - 双链表(C++)
  15. 如何编写一个带命令行参数的Python文件
  16. C#操作SqlServer MySql Oracle通用帮助类Db_Helper_DG(默认支持数据库读写分离、查询结果实体映射ORM)
  17. Repair MySQL 5.6 GTID replication by injecting empty transactions
  18. tomcat原理(二)
  19. Ribbon负载均衡策略配置
  20. 操作系统介绍-操作系统历史,IO,进程的三态,同步异步阻塞非阻塞

热门文章

  1. 使用css counter来美化代码片段的样式
  2. Java源代码之LinkedHashMap
  3. golang中并发sync和channel
  4. 深入Asyncio(六)Tasks and Futures
  5. EasyNVR流媒体服务器网页兼容调试:ie浏览器下的接口调用成功但页面无法显示实时的数据
  6. kindeditor浏览器兼容性问题
  7. 【Android】Android中AlertDialog对话框的使用实例
  8. java.lang.UnsupportedClassVersionError: org/openqa/selenium/WebDriver : Unsupported major.minor version 51.0
  9. 【linux】如何给sudo的root设置环境变量
  10. log4j 2 入门实例(2)