平衡树好题

原题传送门

这道题要用Splay,我博客里有对Splay的详细介绍

这道题思维有点难,要把被摧毁的节点插入平衡树,而不是把没有摧毁的节点插入

先把0和n+1插入平衡树,作为边界

操作1:摧毁节点,把该点插入平衡树

操作2:修复最后一个被摧毁节点的位置的可以用栈来求出,并把该点位置从平衡树中删除

操作三:搞一个vis数组,记录是否被摧毁,如果被摧毁了,直接输出0,没被摧毁的话,输出该点后继的位置-该点前驱的位置-1,这应该也很好理解qaq

剩下就没什么问题了(除了代码有点长)

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define root tree[0].ch[1]
#define inf 1000000005
using namespace std;
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[36];int cnt=0;
while(x)sta[cnt++]=x%10,x/=10;
while(cnt)putchar(sta[--cnt]+48);
}
inline int Min(register int a,register int b)
{
return a<b?a:b;
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
struct Splay{
int fa,ch[2],v,sum,rec;
}tree[50005];
int tot=0;
inline bool findd(register int x)
{
return x==tree[tree[x].fa].ch[0]?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
tree[x].fa=fa;
tree[fa].ch[son]=x;
}
inline void update(register int x)
{
tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline void rotate(register int x)
{
int Y=tree[x].fa;
int R=tree[Y].fa;
int Yson=findd(x);
int Rson=findd(Y);
int B=tree[x].ch[Yson^1];
connect(B,Y,Yson);
connect(Y,x,Yson^1);
connect(x,R,Rson);
update(Y),update(x);
}
inline void splay(register int x,register int to)
{
to=tree[to].fa;
while(tree[x].fa!=to)
{
int y=tree[x].fa;
if(tree[y].fa==to)
rotate(x);
else if(findd(x)==findd(y))
rotate(y),rotate(x);
else
rotate(x),rotate(x);
}
}
inline int newpoint(register int v,register int fa)
{
tree[++tot].v=v;
tree[tot].fa=fa;
tree[tot].sum=tree[tot].rec=1;
return tot;
}
inline void Insert(register int x)
{
int now=root;
if(root==0)
{
newpoint(x,0);
root=tot;
}
else
{
while(19260817)
{
++tree[now].sum;
if(x==tree[now].v)
{
++tree[now].rec;
splay(now,root);
return;
}
int nxt=x<tree[now].v?0:1;
if(!tree[now].ch[nxt])
{
int p=newpoint(x,now);
tree[now].ch[nxt]=p;
splay(p,root);
return;
}
now=tree[now].ch[nxt];
}
}
}
inline int find(register int x)
{
int now=root;
while(19260817)
{
if(x==tree[now].v)
{
splay(now,root);
return now;
}
int nxt=x<tree[now].v?0:1;
if(!tree[now].ch[nxt])
return 0;
now=tree[now].ch[nxt];
}
}
inline void delet(register int x)
{
int pos=find(x);
if(!pos)
return;
if(tree[pos].rec>1)
{
--tree[pos].rec;
--tree[pos].sum;
}
else
{
if(!tree[pos].ch[0]&&!tree[pos].ch[1])
root=0;
else if(!tree[pos].ch[0])
{
root=tree[pos].ch[1];
tree[root].fa=0;
}
else
{
int left=tree[pos].ch[0];
while(tree[left].ch[1])
left=tree[left].ch[1];
splay(left,tree[pos].ch[0]);
connect(tree[pos].ch[1],left,1);
connect(left,0,1);
update(left);
}
}
}
inline int lower(register int v)
{
int now=root,ans=-inf;
while(now)
{
if(tree[now].v<v&&tree[now].v>ans)
ans=tree[now].v;
if(tree[now].v>v)
now=tree[now].ch[0];
else
now=tree[now].ch[1];
}
return ans;
}
inline int upper(register int v)
{
int now=root,ans=inf;
while(now)
{
if(tree[now].v>v&&tree[now].v<ans)
ans=tree[now].v;
if(tree[now].v>v)
now=tree[now].ch[0];
else
now=tree[now].ch[1];
}
return ans;
}
bool vis[50005];
int stac[50005],top=-1;
int main()
{
memset(vis,false,sizeof(vis));
int n=read(),m=read();
Insert(0);
Insert(n+1);
while(m--)
{
char ch=getchar();
while(ch!='D'&&ch!='R'&&ch!='Q')
ch=getchar();
if(ch=='D')
{
int x=read();
vis[x]=true;
stac[++top]=x;
Insert(x);
}
else if(ch=='R')
{
vis[stac[top]]=false;
delet(stac[top--]);
}
else
{
int x=read();
if(vis[x])
puts("0");
else
{
write(upper(x)-lower(x)-1);
printf("\n");
}
}
}
return 0;
}

【题解】Luogu P1503 鬼子进村的更多相关文章

  1. luogu P1503 鬼子进村

    嘟嘟嘟 线段树好题. 其实挺水的,想暴力怎么做:每一次从这个点开始向两边扩,直到遇到第一个摧毁的房屋. 那么把暴力改成倍增,然后线段树查询区间和是否为0.时间复杂度O(nlog2n). 题解好像有线段 ...

  2. Luogu P1503 鬼子进村 set

    还是拿set搞... 用set记录每个被摧毁的位置,Q的时候二分一下,在和上一个摧毁的位置减一下,即可求出能到的房子数 #include<iostream> #include<cst ...

  3. 洛谷 P1503 鬼子进村 解题报告

    P1503 鬼子进村 题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. ...

  4. 洛谷P1503 鬼子进村 [平衡树,STL]

    题目传送门 鬼子进村 题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. ...

  5. 洛谷—— P1503 鬼子进村

    https://www.luogu.org/problemnew/show/P1503 题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的 ...

  6. P1503 鬼子进村

    题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. 题目描述 描述 县城里 ...

  7. 洛谷 P1503 鬼子进村

    题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. 题目描述 描述 县城里 ...

  8. 洛谷 P1503鬼子进村

    题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. 题目描述 描述 县城里 ...

  9. 鬼子进村 fhq-treap

    鬼子进村 fhq-treap 题面 观察题目发现可用平衡树做:每次鬼子拆家即从平衡树中加入被拆的节点:每次村民修房子都向平衡树中删除该节点:每次查询时,只需要求出其后驱与前驱,易知nxt-pre-1为 ...

随机推荐

  1. max_execution_time with sleep

    Under Linux, sleeping time is ignored, but under Windows, it counts as execution time. Note The set_ ...

  2. ubuntu下ldd,查看程序动态库信息

    ldd  list, dynamic, dependencies linux-vdso.so. => (0x00007ffe9d9b6000) libstdc++.so. => /usr/ ...

  3. Spring框架第一天

    ## 今天课程:Spring框架第一天 ## ---------- **Spring框架的学习路线** 1. Spring第一天:Spring的IOC容器之XML的方式,Spring框架与Web项目整 ...

  4. gitlab数据迁移至其他gitlb服务器上

    需求: A : 待迁移服务器,上边存有数据 B:接收项目得服务器,本身存在数据 验证方案: 一,搭建gitlab8.15.2 OS:rhel7.4 yum install policycoreutil ...

  5. 安装Esxi 6.5

    最详细安装Esxi 6.5     Exsi 是一款虚拟化系统,与VMware,VirtualBox不同,它不需要安装在其他操作系统上,直接运行在裸机上:占用系统资源很小,易于管理,所以被大多数中小型 ...

  6. <6>Cocos Creator​​​​​​​调试

    高手在于调试,下面来谈Cocos Creator调试! 1. 网页平台调试 调试常见的三种形式为调试打印.运行时报错与断点调试,这里主要利用编辑器"VS Code"与"C ...

  7. Sitecore营销自动化

    增加与战略性自动化营销系统的互动 Sitecore营销自动化基于DMS中的Sitecore个性化功能.营销自动化系统使用诸如位置,设备和先前访问或购买之类的客户数据来影响用户沿着购买路径的旅程.这些系 ...

  8. sitecore系统教程之架构概述

    Sitecore体验数据库(xDB)从实时大数据存储库中的所有通道源收集所有客户交互.它连接交互数据,为每个客户创建全面,统一的视图,并使营销人员可以使用数据来管理客户的实时体验. xDB架构非常灵活 ...

  9. JavaScript 基础,登录验证

    1.<script></script>的三种用法: a.放在<body>中 b.放在<head>中 c.放在外部JS文件中 <!DOCTYPE h ...

  10. Visual Assist 10.9.2248 破解版(支持VS2017)

    [1]下载安装包 下载地址:https://download.csdn.net/download/qq_20044811/10597708 [2]安装与破解方法 第一步:关闭VS所有打开窗体 第二步: ...