BZOJ2028:[SHOI2009]会场预约(平衡树版)
浅谈\(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]会场预约(平衡树版)的更多相关文章
- BZOJ2028: [SHOI2009]会场预约(set)
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 425 Solved: 213[Submit][Status][Discuss] Description ...
- 2021.12.08 [SHOI2009]会场预约(平衡树游码表)
2021.12.08 [SHOI2009]会场预约(平衡树游码表) https://www.luogu.com.cn/problem/P2161 题意: 你需要维护一个 在数轴上的线段 的集合 \(S ...
- [LuoguP2161[ [SHOI2009]会场预约 (splay)
题面 传送门:https://www.luogu.org/problemnew/show/P2161 Solution splay 的确有线段树/树状数组的做法,但我做的时候脑残没想到 我们可以考虑写 ...
- 【题解】P2161[SHOI2009]会场预约(set)
[题解][P2161 SHOI2009]会场预约 题目很像[[题解]APIO2009]会议中心 \(set\)大法好啊! 然后我们有个小\(trick\)(炒鸡帅),就是如何优雅地判断线段交? str ...
- SHOI 2009 会场预约 平衡树 STL练习
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- [SHOI2009] 会场预约 - Treap
Description PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也 ...
- P2161 [SHOI2009]会场预约
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- P2161 [SHOI2009]会场预约 (线段树:线段树上的不重复覆盖数)
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- P2161 [SHOI2009]会场预约[线段树/树状数组+二分/STL]
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
随机推荐
- Linux下文件名正常,下载之后在windows打开为乱码
说明:在Linux下编码为utf-8,在windows下位GBK 1. 2. 3. 4. 5. 6. 7. 8.
- linux SPI驱动——spidev之driver(六)
一: spidev_init注册spidev 1: static int __init spidev_init(void) 2: { 3: int status; 4: 5: /* Claim o ...
- iOS --生产JSON格式,创建JSON文件,创建文件夹,指定储存
//生成json文件 - (void)onjson { // 如果数组或者字典中存储了 NSString, NSNumber, NSArray, NSDictionary, or NSNull ...
- python的安装及matplotlib安装
本文通过实践,自行安装了一遍python及matplotlib. 1.用python2.7的最新版本(写本文时,用的2.7.13).因为默认有安装pip,记得安装时选择最后一个添加环境变量,不然还要手 ...
- Ajax学习笔记(2)--load()方法
<head runat="server"> <title></title> <script src="http://localh ...
- restlet验证
1 restlet有无认证对比 无认证: 客户端发起请求 -----> 服务器路由 -----> 访问服务端资源 有认证: 客户端发起请求 -----> 认证 ----->服务 ...
- Xshell 连接centOS虚拟机、centOS内置python版本升级
Xshell 连接虚拟机 前置条件:VMware Workstation 12.5.1.Xshell 5 . centOS 6.6 1.打开虚拟机,输入用户名和密码: 2.输出命令:ifconfig ...
- mooc课程mit 6.00.1x--problem set2解决方法
PAYING THE MINIMUM 计算每月信用卡最低还款额及剩余应还款额 balance = 4842 #还款额 annualInterestRate = 0.2 #年利息比率 monthlyPa ...
- client网络优化方法
减小图片大小(使用WebP格式的图片) 大部分的Facebook应用数据都是图片,因此降低图片的大小就能够较少数据的下载量.从而加快下载速度,这一点在高延迟的网络环境下很重要.Facebook返回给 ...
- Android进程的生命周期
Android系统想要永久的保留一个应用进程差点儿是不可能的.所以系统就须要不断的释放老的或者不太重要的进程以便腾出足够的内存空间来执行新的或者更重要的进程,那么系统怎样决定哪个进程应该保留哪个应该杀 ...