bzoj 4825: [Hnoi2017]单旋【dfs序+线段树+hash】
这个代码已经不是写丑那么简单了……脑子浆糊感觉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】的更多相关文章
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- 【刷题】BZOJ 4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ:4825: [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ 4034"树上操作"(DFS序+线段树)
传送门 •题意 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的 ...
- 4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...
- DFS序+线段树(bzoj 4034)
题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...
- BZOJ 3252题解(贪心+dfs序+线段树)
题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
随机推荐
- 如何通过AS3加载外部SWF文件,调用外部文件文档类的方法?
一个Flash中通过AS3代码的Loader对象加载另一个SWF文件,并访问其中的文档类中的方法. 简单示例: 主文件:Main.fla, Main.as 被调用的文件:called.swf, Cal ...
- [Bzoj1015][JSOI2008]星球大战starwar(并查集)(离线处理)
1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 6849 Solved: 3204[Submit ...
- 洛谷 P3879 [TJOI2010]阅读理解
P3879 [TJOI2010]阅读理解 题目描述 英语老师留了N篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过. 输入输出 ...
- 从ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection
前言 在阅读这篇文章:Announcing Net Core 3 Preview3的时候,我看到了这样一个特性: Docker and cgroup memory Limits We conclude ...
- office outlook 無法開啟 outlook 視窗
例如[無法啟動Microsoft Office Outlook.無法開啟Outlook 視窗.] 1.啟動 Outlook 安全模式outlook.exe /safe2.清除並重新產生目前設定檔的功能 ...
- poj2481 Cows
Description Farmer John's cows have discovered that the clover growing along the ridge of the hill ( ...
- Win7 本地打印后台处理程序服务没有运 怎么办
找到名为Print Spooler的服务,启动类型改为自动,服务状态改为启动即可.
- php验证邮箱
<?php if(isset($_POST['email'])){ $email = $_POST['email']; if(filter_var($email, FILTER_VALIDATE ...
- Python爬虫开发【第1篇】【Scrapy shell】
Scrapy Shell Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据 ...
- C#中,变量前的@符号
看别人写的C#代码,发现有变量前带@,啥意思? string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling& ...