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. PHP:验证邮箱合法性

    文章来源:http://www.cnblogs.com/hello-tl/p/7592304.html /** * [verifyPhone description] 效验邮箱号合法性 * @para ...

  2. form 表单onclick事件 禁止表单form提交

    最近遇到一次处理form数据的过滤,采用了button的onclick事件来检查,发现return false后表单仍然提交了. 于是仔细研究了下onclick.onsubmit.submit集合函数 ...

  3. 全文搜索(A-4)-推荐系统架构

    推荐系统向用户推荐物品有三种情况. 推荐和用户已表示喜欢的物品相似的物品. 推荐和用户有相似偏好的用户喜欢的物品. 推荐包含用户偏好特征的物品.

  4. Codeforces Round #264 (Div. 2) D

    题意: 给出最多5个序列,问这几个序列的最长公共子序列的长度是多少. solution : 脑抽级别我是,第一个序列每个数字位置固定,这样只要维护一个k-1维的偏序集就好了.然后在保证每个位置合法的情 ...

  5. [bzoj1510][POI2006]Kra-The Disks_暴力

    Kra-The Disks bzoj-1510 POI-2006 题目大意:题目链接. 注释:略. 想法:不难发现其实只有前缀最小值是有效的. 进而我们把盘子一个一个往里放,弄一个自底向上的指针往上蹦 ...

  6. codevs——1039 数的划分

    1039 数的划分 2001年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 将整数 ...

  7. 谈谈控制器技术SpringMVC与struts2

    SpringMVC与struts2区别 作为表现层中控制器技术的两大掌门人,有哪些不同神功? 首先struts2是作为类级别的拦截,一个类对应一个request上下文.springmvc是作为方法级别 ...

  8. Ubuntu 16.04在搭建Redis Cluster搭建时,使用gem install redis时出现:ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /var/lib/gems/2.3.0 directory.

    注意:千万不要使用sudo来执行gem install redis. 解决方法: sudo apt-get update sudo apt-get install git-core curl zlib ...

  9. Cisco网络设备命名规则

      1. CISCO 开头的产品都是路由器:2. RSP 开头的都是CISCO7500 系列产品的引擎:3. VIP 开头的产品都是CISCO 7500系列产品的多功能接口处理器模块:4. PA 开头 ...

  10. 2011 ACM-ICPC 成都赛区A题 Alice and Bob (博弈动规)

    题目大意: 有K堆石子,每堆有Ki个.两人的操作能够是:             1 从某一堆拿走一个 假设该堆在此之后没有石子了.就消失             2 合并两个堆        求是否 ...