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. ORM之创建数据库

    ORM之创建数据库 样板:创建表名为UserInfo的表,表的主键可自行写,Django的ORM也可自行创建. from django.db import models class UserInfo( ...

  2. list嵌套,int与str的用法,replace

    #*************************replace(待改,改动值),返回很重要 A = [['libai',89]] A[0][0]=A[0][0].replace('a','af') ...

  3. 关于自定义checkbox-radio标签的样式的方法(label 和 background-position理解)

    label label标签有一个很好的作用就是扩大表单控件元素的点击区域. 一般有两种方法可以达到效果:(1)使用label标签包裹表单控件(2)设置label标签的for属性和表单的id属性一致 这 ...

  4. IIS 和 ASP.NET ISAPI

    前几天有一个朋友在MSN上问我“ASP.NET 从最初的接收到Http request到最终生成Response的整个流程到底是怎样的?”我觉得这个问题涉及到IIS和ASP.NETASP.NET Ru ...

  5. python用模块zlib压缩与解压字符串和文件的方法

    摘自:http://www.jb51.net/article/100218.htm Python标准模块中,有多个模块用于数据的压缩与解压缩,如zipfile,gzip, bz2等等. python中 ...

  6. csu - 1537: Miscalculation (模拟题)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1537 因为给出的式子是必定合法的,只要用两个栈分别保存符号和数字.算出答案后和从左至右算的答案比对 ...

  7. 快速幂取模模板 && 51nod 1013 3的幂的和

    #include <iostream> #include <cstdio> #include <cmath> #include <vector> #in ...

  8. sql将日期按照年月分组并统计数量

    SELECT DATE_FORMAT(releaseDate,"%Y年%m月") AS dates,COUNT(*) FROM t_diary GROUP BY DATE_FORM ...

  9. Rooks-LightOj1005(规律)

    A rook is a piece used in the game of chess which is played on a board of square grids. A rook can o ...

  10. springboot 子模块访问不到对应的页面

    出现如下错误 解决方案 working directory:没有$MODULE_DIR$该选项,自己输入即可. 完成以上操作就可以正常访问页面了.