BZOJ

LOJ

洛谷


这题不难啊,我怎么就那么傻,拿随便一个节点去模拟。。

我们只需要能够维护,将最小值或最大值转到根。模拟一下发现,对于最小值,它的右子树深度不变(如果存在),其余节点深度全部\(+1\),且除右儿子外所有点的父子关系不会改变。最大值同理。

因为右子树和右子树外的所有点的值域是连续的,所以按值域为下标维护线段树,区间加即可。

至于怎么维护右子树的范围?不就是\((val_x,val_{fa[x]})\)吗。。

如果是删除,把它转到根后,对所有点深度\(-1\)即可。

考虑如何插入。插入的位置肯定是它的前驱后继之间啊。所以用set或此时的线段树找到前驱后继,在对应位置插入就行了(线段树似乎有些麻烦)。然后在线段树上更新一下\(dep\)。


//7276kb	824ms
#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5; int n,root,val[N],ref[N],fa[N],son[N][2],opt[N];
std::set<int> st;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
int val[S];
#undef S
#define Upd(rt,v) val[rt]+=v
// #define Update(rt) exist[rt]=exist[ls]||exist[rs]
inline void PushDown(int rt)
{
Upd(ls,val[rt]), Upd(rs,val[rt]), val[rt]=0;
}
void Modify(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) {Upd(rt,v); return;}
if(val[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
}
void Set(int l,int r,int rt,int p,int v)
{
while(l!=r)
{
if(val[rt]) PushDown(rt);
int m=l+r>>1;
p<=m ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
val[rt]=v;
}
int Query(int l,int r,int rt,int p)
{
while(l!=r)
{
if(val[rt]) PushDown(rt);
int m=l+r>>1;
p<=m ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
return val[rt];
}
pr Query2(int l,int r,int rt,int p)
{
while(l!=r)
{
if(val[rt]) PushDown(rt);
int m=l+r>>1;
p<=m ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
return mp(rt,val[rt]);
}
}T; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline int Find(int x)
{
int l=1,r=n,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
#define S 1,n,1
int Insert(int x)
{
if(st.empty()) {st.insert(root=x), T.Set(S,x,1); return 1;}
std::set<int>::iterator it=st.upper_bound(x);
int p,v;
if(it!=st.end()&&!son[*it][0]) son[p=*it][0]=x;
else son[p=*(--it)][1]=x;
st.insert(x), fa[x]=p, T.Set(S,x,v=T.Query(S,p)+1);
return v;
}
int RotateMin()
{
int x=*st.begin();
if(!fa[x]) return 1;
pr v=T.Query2(S,x);
T.Modify(S,fa[x],n,1), T.val[v.first]=1;//T.Set(S,x,1);
son[fa[x]][0]=son[x][1], fa[son[x][1]]=fa[x], fa[x]=0;
son[x][1]=root, fa[root]=x, root=x;
return v.second;
}
int RotateMax()
{
int x=*st.rbegin();
if(!fa[x]) return 1;
pr v=T.Query2(S,x);
T.Modify(S,1,fa[x],1), T.val[v.first]=1;//T.Set(S,x,1);
son[fa[x]][1]=son[x][0], fa[son[x][0]]=fa[x], fa[x]=0;
son[x][0]=root, fa[root]=x, root=x;
return v.second;
}
int DeleteMin()
{
int v=RotateMin(),x=*st.begin();
st.erase(x), T.Modify(S,1,n,-1), fa[root=son[x][1]]=0, son[x][1]=0;
return v;
}
int DeleteMax()
{
int v=RotateMax(),x=*st.rbegin();
st.erase(x), T.Modify(S,1,n,-1), fa[root=son[x][0]]=0, son[x][0]=0;
return v;
} int main()
{
// freopen("splay.in","r",stdin);
// freopen("splay.out","w",stdout); const int Q=read(); int n=0;
for(int i=1; i<=Q; ++i)
if((opt[i]=read())==1) ++n, val[n]=ref[n]=read();
std::sort(ref+1,ref+1+n), ::n=n;
for(int i=1,t=0; i<=Q; ++i)
switch(opt[i])
{
case 1: printf("%d\n",Insert(Find(val[++t]))); break;
case 2: printf("%d\n",RotateMin()); break;
case 3: printf("%d\n",RotateMax()); break;
case 4: printf("%d\n",DeleteMin()); break;
case 5: printf("%d\n",DeleteMax()); break;
}
return 0;
}

BZOJ.4825.[AHOI/HNOI2017]单旋(线段树)的更多相关文章

  1. [BZOJ4825][HNOI2017]单旋(线段树+Splay)

    4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 667  Solved: 342[Submit][Status][ ...

  2. 【BZOJ4825】[Hnoi2017]单旋 线段树+set

    [BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...

  3. 【bzoj4825】[Hnoi2017]单旋 线段树+STL-set

    题目描述 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天 ...

  4. 洛谷P3721 [AH2017/HNOI2017]单旋(线段树 set spaly)

    题意 题目链接 Sol 这题好毒瘤啊.. 首先要观察到几个性质: 将最小值旋转到根相当于把右子树变为祖先的左子树,然后将原来的根变为当前最小值 上述操作对深度的影响相当于右子树不变,其他的位置-1 然 ...

  5. bzoj 4825: [Hnoi2017]单旋 [lct]

    4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...

  6. 4825: [Hnoi2017]单旋

    4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...

  7. 【LG3721】[HNOI2017]单旋

    [LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...

  8. BZOJ:4825: [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  9. 【刷题】BZOJ 4825 [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

随机推荐

  1. 自动把动态的jsp页面(或静态html)生成PDF文档,并且上传至服务器

    置顶2017年11月06日 14:41:04 阅读数:2311 这几天,任务中有一个难点是把一个打印页面自动给生成PDF文档,并且上传至服务器,然而公司框架只有手动上传文档,打印时可以保存为PDF在本 ...

  2. gitlab原理

    GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 其实,说直白点写,他就是个git服务器,和github差不多,只不过,这个gitlab可 ...

  3. Just oj 2018 C语言程序设计竞赛(高级组)H: CBT?

    H: CBT? 时间限制: 1 s      内存限制: 128 MB      提交 我的状态 题目描述 对于二叉树,如果这棵树的节点排布是按行从上到下,每行从左到右挨个放置,中间不会有空闲的节点. ...

  4. IOU和非极大值抑制

    如何判断对象检测算法运作良好呢? 一.交并比(Intersection over union,IoU) 是产生的候选框(candidate bound)与原标记框(ground truth bound ...

  5. SpringMVC之使用ResponseEntity,java接口返回HttpStatus

    Post请求 一般情况下,在非必须的情况下,使用Jquery实现post请求,而后台返回一般都需要手动封装ResponseUtil,和使用@ResponseBody注解来实现返回.然而我们书上学到的关 ...

  6. windows下KafkaOffsetMonitor下载及安装

    KafkaOffsetMonitor是一个可视化工具的jar包,如KafkaOffsetMonitor-assembly-0.2.1.jar,用来来监控kafka的使用状态. 一.下载地址 https ...

  7. expect 安装 salt 客户端

    #!/bin/bash for i in $(cat ./host.txt) do echo $i > ./tmp.txt HOSTNAME=$(cut -d ':' -f1 ./tmp.txt ...

  8. Ubuntu强制重启后提示emergency mode

    起因 win10+Ubuntu16.04双系统,在ubuntu下训练一个卷积网但是显存拙计卡死了,于是手贱强制按下电源开关重启. 现象 重启后从grub进ubuntu,并不进图形化的登录界面,而是提示 ...

  9. dnsjava usage

    linux dig 命令使用方法 https://www.imooc.com/article/26971?block_id=tuijian_wz https://jimwayne.blogspot.c ...

  10. 安装和强行卸载fuse

    先卸载 yum list fuse yum --setopt=tsflags=noscripts remove fuse.x86_64 安装 yum install automake gcc-c++ ...