LCT

昨天调试一天没出来,今天推倒重写还是gg了,内心崩溃照着源代码抄,结果发现自己把原树fa和splay的fa一起维护,各种re。。。

其实我们手玩一下,发现其实树的形态变化很小,那么就可以用lct维护了,查询就是相当于查询点到root的点权和,点权为1

删除什么的手画一下就行了

然后我们要用一个数组维护一下原树形态,因为splay是二叉树,可以很方便地维护树的形态,但是一般的树比较麻烦,因为删除儿子什么的的确很烦。这些信息不能再lct上维护,因为lct上fa会变化,里面的fa是splay的fa,不是原树的fa,就破坏了原树形态,所以不能这样维护

然后就是lct各种操作。。。几个月没写都忘了。。。

#include<bits/stdc++.h>
using namespace std;
const int N = , inf = ;
namespace IO
{
const int Maxlen = N * ;
char buf[Maxlen], *C = buf;
int Len;
inline void read_in()
{
Len = fread(C, , Maxlen, stdin);
buf[Len] = '\0';
}
inline void fread(int &x)
{
x = ;
int f = ;
while (*C < '' || '' < *C) { if(*C == '-') f = -; ++C; }
while ('' <= *C && *C <= '') x = (x << ) + (x << ) + *C - '', ++C;
x *= f;
}
inline void read(int &x)
{
x = ;
int f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << ) + (x << ) + c - ''; c = getchar(); }
x *= f;
}
inline void read(long long &x)
{
x = ;
long long f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << 1ll) + (x << 3ll) + c - ''; c = getchar(); }
x *= f;
}
} using namespace IO;
int m, opt, cnt, key, root;
set<pair<int, int> > s;
namespace LCT
{
int st[N];
struct node {
int size, l, r, c[], fa, tag;
} t[N];
inline bool wh(int x) { return t[t[x].fa].c[] == x; }
inline void update(int x) { t[x].size = t[t[x].c[]].size + t[t[x].c[]].size + ; }
inline bool isroot(int x) { return t[t[x].fa].c[] != x && t[t[x].fa].c[] != x; }
inline void pushdown(int x)
{
if(!t[x].tag) return;
swap(t[x].c[], t[x].c[]);
t[t[x].c[]].tag ^= ;
t[t[x].c[]].tag ^= ;
t[x].tag ^= ;
}
inline void up(int x)
{
int top = ;
st[++top] = x;
while(!isroot(x))
{
x = t[x].fa;
st[++top] = x;
}
for(int i = top; i; --i) pushdown(st[i]);
}
inline void rotate(int x)
{
int y = t[x].fa, z = t[y].fa, w = wh(x);
t[x].fa = z;
if(!isroot(y)) t[z].c[wh(y)] = x;
t[y].c[w] = t[x].c[w ^ ];
t[t[x].c[w ^ ]].fa = y;
t[x].c[w ^ ] = y;
t[y].fa = x;
update(y);
update(x);
}
inline void splay(int x)
{
up(x);
while(!isroot(x))
{
if(!isroot(t[x].fa)) rotate(wh(x) == wh(t[x].fa) ? t[x].fa : x);
rotate(x);
}
}
inline void access(int u)
{
for(int f = ; u; f = u, u = t[u].fa)
{
splay(u);
t[u].c[] = f;
update(u);
}
}
inline void rever(int u)
{
access(u);
splay(u);
t[u].tag ^= ;
}
inline void link(int u, int v)
{
if(!u || !v) return;
rever(u);
t[u].fa = v;
}
inline void cut(int u, int v)
{
if(!u || !v) return;
rever(u);
access(v);
splay(v);
t[v].c[] = t[u].fa = ;
update(v);
}
inline void que(int u)
{
rever(root);
access(u);
splay(u);
printf("%d\n", t[u].size);
}
} using LCT :: link; using LCT :: cut; using LCT :: que;
struct info {
int l, r, fa;
} t[N];
inline void insert(int key)
{
pair<int, int> o = make_pair(key, ++cnt);
set<pair<int, int> > :: iterator it1, it2;
it1 = it2 = s.insert(o).first;
int u = , v = , x = cnt;
if(it1 != s.begin()) u = (--it1) -> second;
if(++it2 != s.end()) v = it2 -> second;
if(u == && v == ) root = x;
else if(v && t[v].l == )
{
t[v].l = x;
t[x].fa = v;
link(v, cnt);
}
else if(u && t[u].r == )
{
t[u].r = x;
t[x].fa = u;
link(u, cnt);
}
que(cnt);
}
inline void splay_min()
{
int u = s.begin() -> second, r = t[u].r, p = t[u].fa;
que(u);
if(u == root) return;
cut(u, p);
cut(u, r);
link(p, r);
link(u, root);
t[u].r = root;
t[root].fa = u;
t[r].fa = p;
t[p].l = r;
root = u;
}
inline void splay_max()
{
set<pair<int, int> > :: iterator it = s.end();
int u = (--it) -> second, l = t[u].l, p = t[u].fa;
que(u);
if(u == root) return;
cut(u, p);
cut(u, l);
link(p, l);
link(u, root);
t[u].l = root;
t[root].fa = u;
t[l].fa = p;
t[p].r = l;
root = u;
}
inline void del_min()
{
set<pair<int, int> > :: iterator it = s.begin();
int u = it -> second, r = t[u].r, p = t[u].fa;
que(u);
if(u == root)
{
cut(u, r);
t[r].fa = ;
root = r;
}
else
{
cut(u, p);
cut(u, r);
link(p, r);
t[r].fa = p;
t[p].l = r;
}
s.erase(it);
}
inline void del_max()
{
set<pair<int, int > > :: iterator it = s.end();
int u = (--it) -> second, l = t[u].l, p = t[u].fa;
que(u);
if(u == root)
{
cut(u, l);
t[l].fa = ;
root = l;
}
else
{
cut(u, p);
cut(u, l);
link(p, l);
t[l].fa = p;
t[p].r = l;
}
s.erase(it);
}
int main()
{
// read_in();
read(m);
while(m--)
{
read(opt);
if(opt == ) read(key), insert(key);
if(opt == ) splay_min();
if(opt == ) splay_max();
if(opt == ) del_min();
if(opt == ) del_max();
}
return ;
}

bzoj4825的更多相关文章

  1. 【BZOJ4825】【HNOI2017】单旋(Link-Cut Tree)

    [BZOJ4825][HNOI2017]单旋(Link-Cut Tree) 题面 题面太长,懒得粘过来 题解 既然题目让你写Spaly 那就肯定不是正解 这道题目,让你求的是最大/最小值的深度 如果有 ...

  2. [BZOJ4825][HNOI2017]单旋(线段树+Splay)

    4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 667  Solved: 342[Submit][Status][ ...

  3. 【BZOJ4825】[Hnoi2017]单旋 线段树+set

    [BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...

  4. BZOJ4825 [Hnoi2017]单旋 【线段树】

    题目链接 BZOJ4825 题解 手模一下操作,会发现一些很优美的性质: 每次旋到根,只有其子树深度不变,剩余点深度\(+1\) 每次旋到根,[最小值为例]右儿子接到其父亲的左儿子,其余点形态不改变, ...

  5. bzoj4825 [Hnoi2017]单旋

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

  6. [BZOJ4825][HNOI2017]单旋spaly

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

  7. BZOJ4825 单旋

    分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap. 画一画图就可以解决这道题了,自己试一下. 代码如下: #include<bits/stdc++.h&g ...

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

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

  9. 【bzoj4825】[Hnoi2017]单旋 线段树+STL-set

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

  10. 刷题总结——单旋(HNOI2017 bzoj4825)

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

随机推荐

  1. javascript事件中'return false'详解

    浏览器中有很多异步事件,如click,mouseenter,mouseover等等,当用户执行相应操作之后,触发这个事件,然后执行相应的事件处理函数,一般情况下,我们可以通过三种方式给元素添加事件处理 ...

  2. 对于BFC(block format context)理解

    目录 前言 Box: CSS布局的基本单位&盒模型 什么是BFC?(Block formatting contexts) 元素与盒 正常流 块级与行内级 产生垂直外边距合并的必备条件 前言 什 ...

  3. 树剖 lca

    GeneralLiu  橙边为轻边 红边为重边 绿数为每个点的 top 橙数为每个点的编号 步骤 1 先预处理 每个点的 deep深度  size子树大小  dad父节点 2 再预处理 每个点的 to ...

  4. K-th Number POJ - 2104 划分树

    K-th Number You are working for Macrohard company in data structures department. After failing your ...

  5. Linux下汇编语言学习笔记51 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  6. 【进击后端】ubuntu 快速安装node mongodb express

    安装软件:node,mongo,express 1.apt install node 2.node -v 3.apt install mongodb 4.mongo -version 5.apt in ...

  7. Codeforces 803F(容斥原理)

    题意: 给n个正整数,求有多少个GCD为1的子序列.答案对1e9+7取模. 1<=n<=1e5,数字ai满足1<=ai<=1e5 分析: 设f(x)表示以x为公约数的子序列个数 ...

  8. Redis基于客户端分片的集群案例(待实践)

    说明: 下面的示例基本都是基于Linux去实现,目的是为了环境的统一,以便于把性能调整到最优.且基于Java.建议生产环境不要使用Windows/Mac OS这些. 在Java领域,基于客户端进行分片 ...

  9. CE310A

    http://v.ku6.com/show/tvWNTLZTVWuGVPE5ZMSUyQ...html

  10. mybatis bug之resultmap缺少object-relation匹配参数password,造成设置密码不成功

    1.mybatis bug之resultmap缺少object-relation匹配参数password,造成设置密码不成功 在resultmap里没有设置user类中password属性和数据库表t ...