题目链接

BZOJ4825

题解

手模一下操作,会发现一些很优美的性质:

每次旋到根,只有其子树深度不变,剩余点深度\(+1\)

每次旋到根,【最小值为例】右儿子接到其父亲的左儿子,其余点形态不改变,然后将该点接到根之上,原根变为其右儿子

每次插入,都是插入到其前驱后继深度较大的那一个点之下

所以我们很容易模拟出树的形态,同时用线段树维护离散化后各权值的深度

#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
set<int> S;
struct Que{
int opt,v;
}Q[maxn];
int fa[maxn],ls[maxn],rs[maxn];
int b[maxn],tot,m;
int getn(int x){return lower_bound(b + 1,b + 1 + tot,x) - b;}
int val[maxn << 2],tag[maxn << 2];
void pd(int u){
if (tag[u]){
val[u << 1] += tag[u]; tag[u << 1] += tag[u];
val[u << 1 | 1] += tag[u]; tag[u << 1 | 1] += tag[u];
tag[u] = 0;
}
}
void change(int u,int l,int r,int pos,int v){
if (l == r) {val[u] = v; return;}
pd(u);
int mid = l + r >> 1;
if (mid >= pos) change(u << 1,l,mid,pos,v);
else change(u << 1 | 1,mid + 1,r,pos,v);
}
void modify(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R) {val[u] += v; tag[u] += v; return;}
pd(u);
int mid = l + r >> 1;
if (mid >= L) modify(u << 1,l,mid,L,R,v);
if (mid < R) modify(u << 1 | 1,mid + 1,r,L,R,v);
}
int query(int u,int l,int r,int pos){
if (l == r) return val[u];
pd(u);
int mid = l + r >> 1;
if (mid >= pos) return query(u << 1,l,mid,pos);
return query(u << 1 | 1,mid + 1,r,pos);
}
void print(int u,int l,int r){
if (l == r) printf("%d ",val[u]);
else {
pd(u);
int mid = l + r >> 1;
print(u << 1,l,mid);
print(u << 1 | 1,mid + 1,r);
}
}
int main(){
m = read(); int n = 0;
REP(i,m){
Q[i].opt = read();
if (Q[i].opt == 1) b[++n] = Q[i].v = read();
}
sort(b + 1,b + 1 + n); tot = 1;
for (int i = 2; i <= n; i++) if (b[i] != b[tot]) b[++tot] = b[i];
S.insert(0); S.insert(tot + 10);
int pre,nxt,d1,d2,u,v,rt;
for (int i = 1; i <= m; i++){
if (Q[i].opt == 1){
u = getn(Q[i].v);
S.insert(u);
pre = *--S.find(u);
nxt = *++S.find(u);
if (pre == 0 && nxt == tot + 10)
change(1,1,tot,u,1),rt = u;
else if (pre == 0){
d1 = query(1,1,tot,nxt);
change(1,1,tot,u,d1 + 1);
fa[u] = nxt; ls[nxt] = u;
}
else if (nxt == tot + 10){
d2 = query(1,1,tot,pre);
change(1,1,tot,u,d2 + 1);
fa[u] = pre; rs[pre] = u;
}
else {
d1 = query(1,1,tot,nxt);
d2 = query(1,1,tot,pre);
if (d1 > d2){
change(1,1,tot,u,d1 + 1);
fa[u] = nxt; ls[nxt] = u;
}
else {
change(1,1,tot,u,d2 + 1);
fa[u] = pre; rs[pre] = u;
}
}
ls[u] = rs[u] = 0;
printf("%d\n",query(1,1,tot,u));
}
else if (Q[i].opt == 2){
u = *++S.find(0);
printf("%d\n",query(1,1,tot,u));
if (!fa[u]) continue;
modify(1,1,tot,fa[u],tot,1);
change(1,1,tot,u,1);
v = fa[u];
ls[v] = rs[u]; if (rs[u]) fa[rs[u]] = v;
rs[u] = rt; fa[rt] = u; fa[u] = 0;
rt = u;
}
else if (Q[i].opt == 3){
u = *--S.find(tot + 10);
printf("%d\n",query(1,1,tot,u));
if (!fa[u]) continue;
modify(1,1,tot,1,fa[u],1);
change(1,1,tot,u,1);
v = fa[u];
rs[v] = ls[u]; if (ls[u]) fa[ls[u]] = v;
ls[u] = rt; fa[rt] = u; fa[u] = 0;
rt = u;
}
else if (Q[i].opt == 4){
u = *++S.find(0);
printf("%d\n",query(1,1,tot,u));
if (fa[u]) modify(1,1,tot,u,fa[u] - 1,-1);
else modify(1,1,tot,1,tot,-1);
if (v = fa[u]){
ls[v] = rs[u]; if (rs[u]) fa[rs[u]] = v;
rs[u] = 0;
}
else if (rs[u]) fa[rs[u]] = 0,rt = rs[u],rs[u] = 0;
S.erase(u);
}
else if (Q[i].opt == 5){
u = *--S.find(tot + 10);
printf("%d\n",query(1,1,tot,u));
if (fa[u]) modify(1,1,tot,fa[u] + 1,u,-1);
else modify(1,1,tot,1,tot,-1);
if (v = fa[u]){
rs[v] = ls[u]; if (ls[u]) fa[ls[u]] = v;
ls[u] = 0;
}
else if (ls[u]) fa[ls[u]] = 0,rt = ls[u],ls[u] = 0;
S.erase(u);
}
/*printf("rt = %d\n",b[rt]);
for (int i = 1; i <= tot; i++){
printf("node%d fa = %d ,ls = %d rs = %d\n",b[i],b[fa[i]],b[ls[i]],b[rs[i]]);
}
print(1,1,tot); puts("");*/
}
return 0;
}

BZOJ4825 [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. BZOJ.4825.[AHOI/HNOI2017]单旋(线段树)

    BZOJ LOJ 洛谷 这题不难啊,我怎么就那么傻,拿随便一个节点去模拟.. 我们只需要能够维护,将最小值或最大值转到根.模拟一下发现,对于最小值,它的右子树深度不变(如果存在),其余节点深度全部\( ...

  5. 洛谷P3721 [AH2017/HNOI2017]单旋(线段树 set spaly)

    题意 题目链接 Sol 这题好毒瘤啊.. 首先要观察到几个性质: 将最小值旋转到根相当于把右子树变为祖先的左子树,然后将原来的根变为当前最小值 上述操作对深度的影响相当于右子树不变,其他的位置-1 然 ...

  6. bzoj4825 [Hnoi2017]单旋

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

  7. BZOJ4825: [Hnoi2017]单旋(Splay)

    题面 传送门 题解 调了好几个小时--指针太难写了-- 因为只单旋最值,我们以单旋\(\min\)为例,那么\(\min\)是没有左子树的,而它旋到根之后,它的深度变为\(1\),它的右子树里所有节点 ...

  8. [BZOJ4825][HNOI2017]单旋spaly

    BZOJ Luogu 题目太长了,就不放了. 题解 首先声明一点,无论是splay还是spaly,插入一个新的元素,都要rotate到根!所以说题目也算是给了一个错误示范吧. 我们发现把最值旋转到根并 ...

  9. 4825: [Hnoi2017]单旋

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

随机推荐

  1. html编写头部,mata的含义

    <meta name="viewport" content="width=device-width, initial-scale=1.0"> con ...

  2. Delphi中DLL的创建和使用(转)

    Delphi中DLL的创建和使用     1.DLL简介:   2.调用DLL:   3.创建DLL:   4.两个技巧:   5.初始化:   6.例外处理.            1.DLL简介  ...

  3. 【js】【跨域问题】前后端分离的跨域问题

    最近在研究nodejs,php的前后端分离相关东西,在调用接口的时候碰到一些跨域的问题,经过一段时间的摸索,总结出来的一些东西 php采用的是yii框架,登录的机制或者调用接口都需要前端传递cooki ...

  4. 1016-02-首页17-添加转发微博控件-计算转发配图的 Frame-------打印出 被转发微博的模型

    说明:HWStatus为微博模型,_retweeted_status 为返回的数据( 一条微博模型)里面的一个属性,_retweeted_status 不为空表示此微博是否转发了其他微博._retwe ...

  5. CentOS 使用 LAMP 环境开启 SSL 搭建 WordPress

    环境阿里云新装CentOS 7.4, 使用yum(非编译安装)搭建LAMP, CA证书为阿里云免费提供的, WordPress为官网下载 安装 LAMP 并开启 HTTPS 1, 关闭防火墙 # sy ...

  6. 11,flask之--WTForms

    WTForms是什么? 相当于django的ModelForm. 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据 ...

  7. 3226: [Sdoi2008]校门外的区间

    链接 思路 bug漫天飞... 维护一颗线段树,支持区间赋值,和区间异或.因为会处理到一些方括号还是圆括号的问题,所以对于每一个下标都乘2,假设中间有一个.5即可,都变成了方括号,输出在处理一下. U ...

  8. 亲手搭建一个基于Asp.Net WebApi的项目基础框架1

    目标:教大家搭建一个简易的前后端分离的项目框架. 目录: 1:关于项目架构的概念 2:前后端分离的开发模式 3:搭建框架的各个部分 这段时间比较闲,所以想把之前项目里用到的一些技术写到博客里来,分享给 ...

  9. Android学习记录(7)—Intent中显示意图和隐式意图的用法

    Intent(意图)主要是解决Android应用的各项组件之间的通讯. Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的 ...

  10. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目11

    2014-03-21 20:20 题目:给定一个只包含‘0’.‘1’.‘|’.‘&’.‘^’的布尔表达式,和一个期望的结果(0或者1).如果允许你用自由地给这个表达式加括号来控制运算的顺序,问 ...