这个代码已经不是写丑那么简单了……脑子浆糊感觉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. poj2723 2sat判断解+二分

    典型的2-sat问题,题意:有m个门,每个门上俩把锁,开启其中一把即可,现在给n对钥匙(所有 钥匙编号0123456...2n-1),每对钥匙只能用一把,要求尽可能开门多(按顺序,前max个). 关键 ...

  2. PostgreSQL 9.3.1 中文手册(解决关键词报错的问题)

    http://www.postgres.cn/docs/9.3/sql-keywords-appendix.html

  3. Java的finally语句在try或catch中的return语句执行之后还是之前?

    import java.util.HashMap; import java.util.Map; public class FinallyDemo1 { public static void main( ...

  4. SQL2008安装时,“provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接) (.Net SqlClient Data Provider)” 错误的解决方案

    错误提示: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provide ...

  5. ES文件浏览器 WIFI 查看电脑文件怎么弄

    1 开启来宾账户   2 右击要共享的文件夹,添加Guest共享(如果只是要查看共享的资源,权限级别为读取即可)   3 共享之后,网络路径就是"\\"+你的计算机名+" ...

  6. 各种“GND”

    资料来自网上,把个人觉得靠谱的摘取下来 1.地分类: a)直流地:直流电路“地”,零电位参考点: b)交流地:交流电的零线.要与地线区别开,不过,有时候拉电入户之前会把地线和零线接在一起: c)功率地 ...

  7. hdu2099 整除的位数(暴力)

    Problem Description http://acm.hdu.edu.cn/showproblem.php?pid=2099 一个整数,仅仅知道前几位.不知道末二位,被还有一个整数除尽了,那么 ...

  8. Java小白手记2:一些名词解释

    看到<Java 征途:行者的地图> ,这是一篇有关java学习路径文章.对我等Java小白有指引作用.里面提到了一些基本的名词术语,有些我知道,有些不知道,再补上一些自己曾觉得模糊的,记录 ...

  9. NYOJ110 剑客决斗

    剑客决斗 来源:Polish Olympiad in Informatics(波兰信息学奥林匹克竞赛) 时间限制:5000 ms  |  内存限制:65535 KB 难度:5   描述 在路易十三和红 ...

  10. mysql数据库存放路径

    在你的my.ini 文件中定义的参数 datadir 指定的目录中. SQL code ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 mysql> select @@da ...