splay维护dfs序

我们发现有移动子树这种操作,树剖是做不了了,又要实现子树加,lct又维护不了了,这时我们用splay维护入栈出栈序来支持这些操作。我们记录每个点的入栈时间和出栈时间,这样一个闭合的区间就表示了一个节点的子树,于是我们可以支持更换父亲了。然后是子树加,这里我们把要加的区间提取出来,打标记,但是我们还得维护一个符号总和,因为入栈时间加,出栈时间要减去加的值,因为出栈时间之后得序列就不属于这棵子树了。最后是查询,查询我们只要把查询节点的入栈时间和1号节点提取出来,然后总和就是答案。注意提取区间时不是in[x]-1,out[x]+1,虽然这里节点编号就是对应排名,但是因为这里是出栈入栈序,所以+1-1不一定是序列中下一个节点,所以我们要查询前继后继,也就是提取pre(in[x])和nxt(out[x])

然后还卡时间,我用fread卡过去了

#include<bits/stdc++.h>
using namespace std;
const int N = , Maxlen = * N;
int n, m, dfs_clock = , root;
int in[N], out[N];
long long w[N];
vector<int> G[N];
char buf[Maxlen], *C = buf;
int Len;
inline int read()
{
int x = ;
while (*C < '' || '' < *C) ++C;
while ('' <= *C && *C <= '') x = x * + *C - '', ++C;
return x;
}
namespace Splay_tree
{
int cnt;
int child[N][], fa[N], st[N];
long long sum[N], key[N], tag[N], tim[N], sum_tim[N];
inline bool wh(int x)
{
return child[fa[x]][] == x;
}
inline void update(int x)
{
sum[x] = sum[child[x][]] + sum[child[x][]] + key[x];
sum_tim[x] = sum_tim[child[x][]] + sum_tim[child[x][]] + tim[x];
}
inline void pushdown(int x)
{
if(tag[x] == ) return;
tag[child[x][]] += tag[x];
tag[child[x][]] += tag[x];
key[child[x][]] += tag[x] * tim[child[x][]];
key[child[x][]] += tag[x] * tim[child[x][]];
sum[child[x][]] += tag[x] * sum_tim[child[x][]];
sum[child[x][]] += tag[x] * sum_tim[child[x][]];
tag[x] = ;
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y], t = wh(x);
fa[x] = z;
child[z][wh(y)] = x;
child[y][t] = child[x][t ^ ];
fa[child[x][t ^ ]] = y;
child[x][t ^ ] = y;
fa[y] = x;
update(y);
update(x);
}
inline void up(int x)
{
int top = , now = x;
while(now != root)
{
st[++top] = now;
now = fa[now];
}
st[++top] = root;
for(int i = top; i; --i) pushdown(st[i]);
}
inline void splay(int x, int t)
{
up(x);
for(int f; (f = fa[x]) != t; rotate(x))
if(fa[f] != t) rotate(wh(x) == wh(f) ? f : x);
if(!t) root = x;
}
inline void build(int l, int r, int &x, int last)
{
if(l > r) return;
int mid = (l + r) >> ;
x = mid;
fa[x] = last;
build(l, mid - , child[x][], x);
build(mid + , r, child[x][], x);
update(x);
}
inline int pre(int x)
{
splay(x, );
x = child[x][];
while(child[x][]) x = child[x][];
return x;
}
inline int nxt(int x)
{
splay(x, );
x = child[x][];
while(child[x][]) x = child[x][];
return x;
}
inline void change(int x, int y)
{
int a = pre(in[x]), b = nxt(out[x]);
splay(a, );
splay(b, root);
int t = child[child[root][]][];
fa[t] = child[child[root][]][] = ;
update(child[root][]);
update(root);
a = nxt(in[y]);
splay(in[y], );
splay(a, root);
fa[t] = child[root][];
child[child[root][]][] = t;
update(child[root][]);
update(root);
}
inline void ask(int x)
{
x = nxt(in[x]);
splay(, );
splay(x, root);
int t = child[child[root][]][];
printf("%lld\n", sum[t]);
}
inline void add(int x, int delta)
{
int a = pre(in[x]), b = nxt(out[x]);
splay(a, );
splay(b, root);
int t = child[child[root][]][];
tag[t] += delta;
sum[t] += delta * sum_tim[t];
key[t] += delta * tim[t];
}
} using namespace Splay_tree;
void dfs(int u)
{
in[u] = ++dfs_clock;
tim[in[u]] = ;
key[in[u]] = w[u];
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
dfs(v);
}
out[u] = ++dfs_clock;
key[out[u]] = -w[u];
tim[out[u]] = -;
}
int main()
{
// freopen("galaxy20.in", "r", stdin);
// freopen("output.txt", "w", stdout);
Len = fread(C, , Maxlen, stdin);
buf[Len] = '\0';
n = read();
for(int i = ; i <= n; ++i)
{
int u = read();
G[u].push_back(i);
}
for(int i = ; i <= n; ++i) w[i] = read();
dfs();
++dfs_clock;
build(, dfs_clock, root, );
m = read();
while(m--)
{
char c;
int x, y;
for(c = *C; c < 'A' || c > 'Z'; ++C, c = *C);
if(c == 'Q')
{
x = read();
ask(x);
}
if(c == 'C')
{
x = read();
y = read();
change(x, y);
}
if(c == 'F')
{
x = read();
y = read();
add(x, y);
}
}
// fclose(stdin);
// fclose(stdout);
return ;
}

bzoj3786的更多相关文章

  1. [BZOJ3786]星系探索

    [BZOJ3786]星系探索 试题描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个 ...

  2. 【BZOJ3786】星系探索 DFS序+Splay

    [BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...

  3. BZOJ3786 星系探索 【Splay维护dfs序】*

    BZOJ3786 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均 ...

  4. [BZOJ3786]星系探索(伪ETT)

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1638  Solved: 506[Submit][Status][Discuss ...

  5. BZOJ3786 星际探索

    @(BZOJ)[DFS序, Splay] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其 ...

  6. [BZOJ3786] 星系探索(括号序列+Splay)

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 2191  Solved: 644[Submit][Status][Discuss ...

  7. 【BZOJ-3786】星系探索 Splay + DFS序

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 647  Solved: 212[Submit][Status][Discuss] ...

  8. bzoj3786星系探索 splay

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1314  Solved: 425[Submit][Status][Discuss ...

  9. BZOJ3786星系探索——非旋转treap(平衡树动态维护dfs序)

    题目描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. ...

  10. BZOJ3786: 星系探索 Splay+DFS序

    题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...

随机推荐

  1. 洛谷 2187 小Z的笔记

    [题解] DP.  设f[i]表示前i个字母,保留第i个字母,最多可以保留多少个字母:设g[i]为当前字母为i的位置对应的f的最大值. 转移方程就是f[i]=max(f[i], g[j]+1) (j与 ...

  2. [bzoj1078][SCOI2008][斜堆] (贪心)

    Description 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的堆性质:每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小.但斜堆不必是平衡的,每个结 ...

  3. 2016 Multi-University Training Contest 3-1011.Teacher Bo,暴力!

    Teacher Bo                                                         Time Limit: 4000/2000 MS (Java/Ot ...

  4. 「CodePlus 2017 11 月赛」Yazid 的新生舞会

    n<=500000的数字,问有多少个区间的众数出现次数严格大于区间长度的一半. 这么说来一个区间就一个众数了,所以第一反应是枚举数字,对下标进行处理.然后没有第二反应.很好. 在枚举一个数字的时 ...

  5. ZOJ 1298_Domino Effect

    题意: 多米诺骨牌效应:若干个关键牌相连,关键牌之间含有普通牌,关键牌倒下后其所在的行的普通牌全部倒下.求从推倒1号关键牌开始,最终倒下的牌的位置及时间. 分析: 最终倒下的牌的位置有两种情况,要么是 ...

  6. Search Insert Position(二分查找)

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  7. neutron dhcp

    neutron dhcp 采用dnsmasq服务来实现.和传统的 dhcp 一样, dhcp请求也分为4步 The client sends a discover ("I'm a clien ...

  8. 1076. Forwards on Weibo (30)【树+搜索】——PAT (Advanced Level) Practise

    题目信息 1076. Forwards on Weibo (30) 时间限制3000 ms 内存限制65536 kB 代码长度限制16000 B Weibo is known as the Chine ...

  9. leetcode02-Add Two Numbers之beats98.68%Java版本号

    我的leetcode之旅,该篇章主要完毕使用Java实现算法. 这是第二篇Add Two Numbers 所有代码下载: Github链接:github链接,点击惊喜; 写文章不易.欢迎大家採我的文章 ...

  10. 通过构建Cocoapods私有库进行组件化开发探索

    专题一 一.创建私有索引库 选Github或者码云都可以,本例以Github为例.创建私有索引库用来作为自己组件库的索引: 二.本地添加私有索引库 添加:pod repo add 索引库名称 索引库地 ...