这个代码已经不是写丑那么简单了……脑子浆糊感觉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. csu - 1659 Graph Center(最短路)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1659 题意是找一个图的中心,图的中心定义是某一个点到其他点的最大距离最小,如果有多个排序输出. 注 ...

  2. [Bzoj2120]数颜色 (非正解 )(莫队)

    2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 6286  Solved: 2489[Submit][Status][Discuss] ...

  3. PCRE函数简介和使用示例

    PCRE是一个NFA正则引擎,不然不能提供完全与Perl一致的正则语法功能.但它同时也实现了DFA,只是满足数学意义上的正则. PCRE提供了19个接口函数,为了简单介绍,使用PCRE内带的测试程序( ...

  4. 生产环境之Nginx高可用方案

    准备工作: 192.168.16.128 192.168.16.129 两台虚拟机.安装好Nginx 安装Nginx 更新yum源文件: rpm -ivh http://nginx.org/packa ...

  5. delphi 修改文件夹名和文件名

    unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Form ...

  6. Friefox清除旧的网页缓存

    Ctrl + F5 适用于调试网页编码时,不断以旧设置显示页面

  7. 选带傅里叶变换(zoom-fft)

    选带傅里叶变换的原理大家能够看书.大致的步骤为 移频 (将选带的中心频率移动到零频) 数字低通滤波器  (防止频率混叠) 又一次採样  (将採样的数据再次间隔採样,间隔的数据取决于分析的带宽,就是放大 ...

  8. easyui英文提示变中文

    近期玩JQuery easyUI,系统默认的日期和文本输入框提示英文.作为一个地道的中国人,是不是提示成中文.日期也显示成中文,是不是更人性化呢,下面为操作方法哦. 更改前效果 1 输入框提示为英文 ...

  9. 输入年份,然后打印出该年的万年历,以及标识出当天日期。相似于linux下的cal -y结果。

    public class Permanent { public static boolean isLeapYear(int year){//能被4整除但不能被100整除.或者能被400整除 boole ...

  10. Latex 2: 解决WinEdt和TexWorks用久之后忽然不能正反向搜索

    说明:下面说的WinEdt版本是10.1,TexWorks是texlive2016中自带的texworks,如果情况不一样请自行测试,原理一样 1.不能正向搜索: 解决:① 确定路径名是英文名(实际上 ...