首页 > 其他分享 >P2161 [SHOI2009]会场预约 题解

P2161 [SHOI2009]会场预约 题解

时间:2023-02-24 13:36:03浏览次数:59  
标签:cnt ch int 题解 P2161 fa SHOI2009 root wx

没事打了个Splay,然后调了3h。

觉得题解的找前驱后继与删除复杂了点,主要讲一下这的思路。

由于平衡树中每一个点代表的区间互不相交,所有平衡树满足 \(l,r\) 两个值的BST。

以 \(l\) 为第一关键字排序,其他操作同Splay。

找后继的时候插入一个 \((r,r)\) 的点,然后旋转至顶端,找到自己的右儿子的最左边。

记得要删除 \((r,r)\)。

剩下的就是求前驱了,求前驱仍然插入一个 \((l,l)\) 的点,但此时如果只找左儿子的最右边会出问题,因为求前驱时要求的是满足最大的 \(r_i < l\),所以有可能不满足条件,那么将分情况讨论。


1、无左儿子,为父亲节点。

2、有左儿子,为左儿子的最右边。

分情况讨论即可。

理论复杂度为 \(O(n)\),但实际上便历过的点都是要删的,所以复杂度不高。

最后将前驱延展到根节点,后继延展到根节点的右儿子,删除后继的左儿子即可,即赋值为 \(0\)。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=6e5+5;
int n,cnt,root;
struct node
{
	int fa,ch[2],x,y,cnt,siz;
}t[N];
inline void newnode(int &x,int fa,int wx,int wy)
{
	x=++cnt;
	t[x].fa=fa;
	t[x].x=wx;
	t[x].y=wy;
	t[x].cnt=t[x].siz=1;
}
inline void connect(int x,int fa,int son)
{
	t[x].fa=fa;
	t[fa].ch[son]=x;
}
inline bool ident(int x,int fa)
{
	return t[fa].ch[1]==x;
}
inline void pushup(int x)
{
	t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+t[x].cnt;
}
inline void rotate(int x)
{
	int fa=t[x].fa,ff=t[fa].fa,k=ident(x,fa);
	connect(t[x].ch[k^1],fa,k);
	connect(fa,x,k^1);
	connect(x,ff,ident(fa,ff));
	pushup(fa),pushup(x);
}
void splay(int x,int topp=0)
{
	if(topp==0)root=x;
	while(t[x].fa!=topp)
	{
		int fa=t[x].fa,ff=t[fa].fa;
		if(ff!=topp)ident(x,fa)^ident(fa,ff)?rotate(x):rotate(fa);
		rotate(x);
	}
}
void insert(int wx,int wy,int &x=root,int fa=0)
{
	if(!x)newnode(x,fa,wx,wy),splay(x);
	else if(t[x].x==wx&&t[x].y==wy)t[x].cnt++,splay(x);
	else if(t[x].x>wx)insert(wx,wy,t[x].ch[0],x);
	else insert(wx,wy,t[x].ch[1],x);
}
void erase(int x=root)
{
	if(t[x].cnt>1)t[x].cnt--;
	else if(t[x].ch[1])
	{
		int p=t[x].ch[1];
		while(t[p].ch[0])p=t[p].ch[0];
		splay(p,x),t[p].fa=0,root=p,connect(t[x].ch[0],p,0);
		pushup(p);
	}
	else root=t[x].ch[0],t[root].fa=0;
}
int pre(int val)
{
	insert(val,val);
	int p=t[root].ch[0];
	while(t[p].ch[1])p=t[p].ch[1];
	if(t[p].y>=val)
	{
		if(t[p].ch[0])
		{
			p=t[p].ch[0];
			while(t[p].ch[1])p=t[p].ch[1];
		}
		else p=t[p].fa;
	}
	int res=p;
	erase();
	return res; 
}
int suf(int val)
{
	insert(val,val);
	int p=t[root].ch[1];
	while(t[p].ch[0])p=t[p].ch[0];
	int res=p;
	erase();
	return res;
}
int del(int l,int r)
{
	int x=pre(l),y=suf(r);
	splay(x);
	splay(y,x);
	int ans=t[t[y].ch[0]].siz;
	t[y].ch[0]=0;
	pushup(y),pushup(x);
	return ans;
}
int main()
{
	insert(0,0);
	insert(1e9,1e9);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		char opt;
		scanf("%c",&opt);
		while(opt!='A'&&opt!='B')scanf("%c",&opt);
		if(opt=='A')
		{
			int l,r;
			scanf("%d%d",&l,&r);
			int ans=del(l,r);
			insert(l,r);
			printf("%d\n",ans);
		}
		if(opt=='B')
		{
			int ans=t[root].siz-2;
			printf("%d\n",ans);
		}
	}
	return 0;
}

标签:cnt,ch,int,题解,P2161,fa,SHOI2009,root,wx
From: https://www.cnblogs.com/gmtfff/p/p2161.html

相关文章

  • P3224 [HNOI2012]永无乡 题解
    典型Splay练习题。开始建\(n\)个Splay,每一次建边用并查集判断是否在一个子图,不在就合并,即把一个Splay的所有点全插入到另一个Splay中,需要合并的点可以用vector存储。但......
  • P1763 埃及分数 题解
    做完后发现很多题解都是有些细节问题的,对于向上与向下取整非常混乱。第一次做迭代加深搜索的题,记录一下。所谓迭代加深搜索,就是在求搜索树的深度的问题中,枚举层数,取最优......
  • P4048 [JSOI2010]冷冻波 题解
    首先很好想到我们应该预处理出来每一个巫妖王能攻击到的精灵。那么这就是一个几何题。对于每一组精灵与巫妖王,设巫妖王坐标为\((x_1,y_1)\),精灵坐标为\((x_2,y_2)\)。......
  • P7221 [JSOI2010] 蔬菜庆典 题解
    本题解在求无解的情况下优化了下。通过分析样例,我们可以发现如果一个节点有多个Dlihc,那么这些Dlihc对应的权值必须一样,否则可以无限延伸下去。因为一号节点没有Tnera......
  • P3195 [HNOI2008]玩具装箱 题解
    首先先写dp方程非常简单\(\mathit{f}_{i}=\min(\mathit{f}_{j}+(\mathit{c}_{i}+i-j-1-L-\mathit{c}_{j})^2)\)(其中\(\mathit{c}_{i}\)表示长度前缀和)然后发现括号......
  • U259394 Gmt丶FFF 的基环树 题解
    题目链接:传送门之所以评黑,是因为实在是太难调了。(又回调了)。对于有$40%$的数据,$n\le3000$,这部分我们可以暴力删边,然后暴力求直径即可。那么对于$100%$的数据:首先......
  • P3977 [TJOI2015]棋盘 题解
    前制知识引导状态压缩动态规划:[P1896[SCOI2005]互不侵犯](https://www.luogu.com.cn/problem/P1896)矩阵加速优化:[P1962斐波那契数列](https://www.luogu.com.cn/prob......
  • vscode格式化和保存代码与eslint有冲突问题解决(亲测有效)
    1.问题描述vscode安装了eslint插件,在使用Vue的时候格式化和保存代码都会爆红2.原因因为在使用Vue进行开发我们一般都安装了Vetur插件来对.vue文件进行处理,Vetur自带了......
  • 云原生|kubernetes|CKA真题解析-------(6-10题)
    第六题:service配置 解析:考察两个知识点:deployment控制器内的port命名暴露一个pod内的端口到新建的服务内的这里有一个需要注意的地方,没有告诉你deployment控制器在哪个name......
  • Windows 技术篇 - 远程桌面连接不保存密码、每次都要输入密码问题解决
    https://blog.csdn.net/qq_38161040/article/details/120013883通过 gpedit.msc 打开本次组策略编辑器。选择 模板管理-系统-凭据分配-允许分配保存的凭据用......