这个代码已经不是写丑那么简单了……脑子浆糊感觉np++分分钟想暴起打死我……就这还一遍A过了……

先都读进来hash一下,因为是平衡树所以dfs序直接按照点值来就好

对于每个操作:

1:set维护已插入的值,对新加入的x找到它的前驱后继,选深度大的挂上去(画图找规律,我也不知道为什么深度较浅的一定挂不上去

2、3:对于这个节点x的右子树,深度不变,x深度变为1,其他点深度+1

4、5:先做2、3操作,然后在set里把这个点删掉,整棵树的深度-1

并不是很难但是情况比较多,导致main函数奇丑无比……

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int N=100005;
int n,ha[N],a[N],tot,has,m,f[N],c[N][2],root;
set<int>st;
typedef set<int>::iterator it;
struct qwe
{
int l,r,de;
}t[N<<2];
struct wen
{
int o,x;
}q[N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void pd(int ro)
{
if(t[ro].de)
{
t[ro<<1].de+=t[ro].de;
t[ro<<1|1].de+=t[ro].de;
t[ro].de=0;
}
}
void build(int ro,int l,int r)
{
t[ro].l=l,t[ro].r=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
}
void jia(int ro,int l,int r,int w)
{
if(l>r)
return;
if(t[ro].l==l&&t[ro].r==r)
{
t[ro].de+=w;
return;
}
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(r<=mid)
jia(ro<<1,l,r,w);
else if(l>mid)
jia(ro<<1|1,l,r,w);
else
{
jia(ro<<1,l,mid,w);
jia(ro<<1|1,mid+1,r,w);
}
}
void update(int ro,int w,int d)
{
if(t[ro].l==t[ro].r)
{
t[ro].de=d;
return;
}
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(w<=mid)
update(ro<<1,w,d);
else if(w>mid)
update(ro<<1|1,w,d);
}
int ques(int ro,int w)
{
if(t[ro].l==t[ro].r)
return t[ro].de;
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(w<=mid)
return ques(ro<<1,w);
else if(w>mid)
return ques(ro<<1|1,w);
}
void add(int x,int y,int d)
{
int de=ques(1,x);
c[x][d]=y;
update(1,y,de+1);
f[y]=x;
st.insert(y);
printf("%d\n",de+1);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
q[i].o=read();
if(q[i].o==1)
q[i].x=read(),a[++tot]=q[i].x;
}
sort(a+1,a+1+tot);
for(int i=1;i<=tot;i++)
if(i==1||a[i]!=a[i-1])
ha[a[i]]=++has;
for(int i=1;i<=n;i++)
if(q[i].o==1)
q[i].x=ha[q[i].x];
build(1,1,tot);
for(int i=1;i<=n;i++)
{
if(q[i].o==1)
{
if(st.empty())
{
update(1,q[i].x,1);
st.insert(q[i].x);
f[q[i].x]=0;
root=q[i].x;
puts("1");
}
else
{
it ne=st.lower_bound(q[i].x);
if(ne==st.begin())
add(*ne,q[i].x,0);
else
{
it pr=ne;
pr--;
if(ne==st.end()||ques(1,*pr)>ques(1,*ne))
add(*pr,q[i].x,1);
else
add(*ne,q[i].x,0);
}
}
}
else if(q[i].o==2)
{
it now=st.begin();
int x=*now,d=ques(1,x);
printf("%d\n",d);
if(d==1)
continue;
jia(1,1,x-1,1);
jia(1,f[x],tot,1);
update(1,x,1);
int rc=c[x][1],p=f[x];
f[x]=0;
c[p][0]=rc;
if(rc)
f[rc]=p;
c[x][1]=root;
f[root]=x;
root=x;
}
else if(q[i].o==3)
{
it now=st.end();
now--;
int x=*now,d=ques(1,x);
printf("%d\n",d);
if(d==1)
continue;
jia(1,1,f[x],1);
jia(1,x+1,tot,1);
update(1,x,1);
int lc=c[x][0],p=f[x];
f[x]=0;
c[p][1]=lc;
if(lc)
f[lc]=p;
c[x][0]=root;
f[root]=x;
root=x;
}
else if(q[i].o==4)
{
it now=st.begin();
int x=*now,d=ques(1,x);
st.erase(x);
printf("%d\n",d);
if(d==1)
{
root=c[x][1];
f[root]=0;
jia(1,1,tot,-1);
continue;
}
jia(1,x+1,f[x]-1,-1);
int rc=c[x][1],p=f[x];
f[x]=0;
c[p][0]=rc;
if(rc)
f[rc]=p;
}
else
{
it now=st.end();
now--;
int x=*now,d=ques(1,x);
st.erase(x);
printf("%d\n",d);
if(d==1)
{
root=c[x][0];
f[root]=0;
jia(1,1,tot,-1);
continue;
}
jia(1,f[x]+1,x-1,-1);
int lc=c[x][0],p=f[x];
f[x]=0;
c[p][1]=lc;
if(lc)
f[lc]=p;
}
}
return 0;
}

bzoj 4825: [Hnoi2017]单旋【dfs序+线段树+hash】的更多相关文章

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

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

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

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

  3. BZOJ:4825: [Hnoi2017]单旋

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

  4. BZOJ 4034"树上操作"(DFS序+线段树)

    传送门 •题意 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的 ...

  5. 4825: [Hnoi2017]单旋

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

  6. DFS序+线段树(bzoj 4034)

    题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...

  7. BZOJ 3252题解(贪心+dfs序+线段树)

    题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...

  8. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  9. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

随机推荐

  1. poj - 3254 Corn Fields (状态压缩dp入门)

    http://poj.org/problem?id=3254 参考:http://blog.csdn.net/accry/article/details/6607703 农夫想在m*n的土地上种玉米, ...

  2. Spring之IOC篇章具体解释

    专题一   IOC 1.接口以及面向接口编程 a.结构设计中,分清层次以及调用关系,每层仅仅向外(或者上层)提供一组功能接口,各层间仅依赖接口而非实现类这样做的优点是,接口实现的变动不影响各层间的调用 ...

  3. 同一个页面多个html、body标签

    同一个页面多个html.body标签 html页面的一些标签,默认只有一个.比如html,head,body..... 如果写多个是什么情况呢.本着好奇的想法,试验了一下. <html> ...

  4. Solr 文章集成

    Solr 文章集成 solr原理 solr wiki: http://wiki.apache.org/solr/ 分布式全文检索系统SolrCloud简单介绍 http://my.oschina.ne ...

  5. C实现头插法和尾插法来构建单链表(不带头结点)

    链表的构建事实上也就是不断插入节点的过程.而节点的插入能够分为头插法和尾插法. 头插法就是在头结点后插入该节点,始终把该节点作为第一个节点.尾插法就是在链表的最后一个节点处插入元素,作为最后一个节点. ...

  6. 求出全部的正整数对 使他们最大公约数为n,最小公倍数为m

    题目大概是这种:cid=1021&pid=5http://" target="_blank">点击打开链接 大意就是 求出全部的正整数对 使他们最大公约数为 ...

  7. Android lowmemorykiller

    drivers/staging/android/lowmemorykiller.c lowmemorykiller 在系统空闲内存不足时, 根据一定机制选择某个进程, 然后杀死它. 1. regist ...

  8. What to do about Eclipse's “No repository found containing: …” error messages?

    As Mauro said: "you have to remove and re-add the Eclipse Project Update site, so that its meta ...

  9. Intellig Idea2017新建Web项目(tu'wen)

    1.新建新工程项目 2.选择Java 和JDK版本 3.下一步Next(默认不勾选) 4.设置Project Name ,点击More Setting图标可以折叠.展开  然后Finish 我们可以看 ...

  10. 转载 Url编码

    http://www.cnblogs.com/artwl/archive/2012/03/07/2382848.html 混乱的URI编码 JavaScript中编码有三种方法:escape.enco ...