题目链接

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. 堆(heap)和栈(stack)几点认识

    堆(heap)和栈(stack)主要的区别由以下几点:1.管理方式不同:2.空间大小不同:3.产生碎片不同:4.生长方向不同:5.分配归属不同:6.分配效率不同:7.存取效率不同:管理方式:对于栈来讲 ...

  2. Java分享笔记:泛型机制的程序演示

    package packA; import java.util.*; public class GenericDemo { public static void main(String[] args) ...

  3. Servlet异步处理和文件上传

    1. 什么是异步处理     原来,在服务器没有结束响应之前,浏览器是看不到响应内容的!只有响应结束时,浏览器才能显示结果!     现在异步处理的作用:在服务器开始响应后,浏览器就可以看到响应内容, ...

  4. mysql学习第三天练习(流程控制函数)

    -- 流程控制函数 -- 1.查询员工部门号,并赋予部门名 select empno,ename,deptno,case deptno then '10部门' then '20部门' else '30 ...

  5. Android面试收集录10 LruCache原理解析

    一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...

  6. 十三、MySQL之IDE工具介绍及数据备份

    一.IDE工具介绍 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具 下载链接:https://pan.baidu.com/s/1bpo5mqj 二.MySQL数据备份 # ...

  7. Spring---BeanFactory与ApplicationContext简介

    BeanFactory概念 Spring通过一个配置文件描述bean和bean之间的依赖关系,然后利用java语言的反射功能实例化bean,并建立bean之间的依赖关系.Spring的IOC容器在完成 ...

  8. hover 改变另一个标签的属性

  9. 如何让button保持点击状态

    http://blog.csdn.net/u010957508/article/details/38385207 他的原理就是在代码里面: view.setSelected(true); 而其他的: ...

  10. web在线调试

    xx <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta h ...