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. 微信浏览器发送ajax请求执行多次解决方法

    http://www.cnblogs.com/whatlonelytear/p/8934738.html

  2. Python字典(Dictionary)

    Python中字典与类表类似,也是可变序列,不过与列表不同,他是无序的可变序列,保存的内容是以键 - 值对的形式存放的.类似我们的新华字典,他可以把拼音和汉字关联起来,通过音节表可以快速的找到想要的字 ...

  3. Linux系统下目录的权限意义

    访问者及其基本权限 Linux系统内的文件访问者有三种身份,分别是: a) 文件和文件目录的所有者: u---User(所有权);b) 文件和文件目录的所有者所在的组的用户: g---Group;c) ...

  4. HDU 1541 STAR(树状数组)

    Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  5. elasticsearch-HQ 安装与使用

    https://github.com/ElasticHQ/elasticsearch-HQ Download or clone the repository. Open terminal and po ...

  6. NEST - Elasticsearch 的高级客户端

    NEST - High level client Version:5.x 英文原文地址:NEST - High level client 个人建议:学习 NEST 的官方文档时,按照顺序进行,不宜跳来 ...

  7. 【Android】Android 4.0 Launcher2源码分析——启动过程分析

    Android的应用程序的入口定义在AndroidManifest.xml文件中可以找出:[html] <manifest xmlns:android="http://schemas. ...

  8. tmux 安装

    安装libevent wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz tar xzv ...

  9. dns-prefetch,新打开页面预抓取

    dns-prefetch 对性能提升有多大 转载2016-04-07 12:57:41 标签:网站推广dns-prefetch对性能提 dns-prefetch, 是DNS预获取,也是网页前端的优化的 ...

  10. Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)

    原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...