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. 原生js获取复选框的值

    ​​ obj = document.getElementsByName("dk_tj"); var longtxt = ""; for (k in obj) { ...

  2. Django开发:(3.1)ORM:单表操作

    MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需 ...

  3. bzoj1834 网络扩容 网络流

    好久没写题解了啊··· 题目大意: 给你一幅n个点的网络,先求出其1到n的最大流,每条弧还会有个属性\(cost_i\),表示没扩容一个单位的费用,现在我们要求的就是扩容K个单位的最小费用 思路: 这 ...

  4. Codeforces698C. LRU

    n<=20种东西,有个大小k<=n的箱子,每次会以固定的概率从所有东西里选一种,若箱子里有空位且这种东西没出现过就丢进去,若箱子满了且这种东西没出现过就把最早访问过的一个丢掉,(只要在每次 ...

  5. openjudge7624 山区建小学

    描述 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < ...

  6. SOJ 3300_Stockholm Coins

    [题意]给n个数,求一个数,使这个数能且只能由(n个数每个至少出现一次)表示.输出满足条件的最小的数. [分析](完全背包)如果有满足条件的最小的数,那么这个数只能是这n个数的和total,通过记录每 ...

  7. POJ 3233_Matrix Power Series

    题意: 求n*n矩阵的幂和 分析: 逐个加起来时间复杂度太高,通过在矩阵中套个矩阵和,再利用矩阵快速幂,最后时间复杂度为O(n3logn) 代码: #include<cstdio> #in ...

  8. [bzoj2962]序列操作_线段树_区间卷积

    序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...

  9. 什么是单点登录(SSO)

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在我实习之前我就已经在看单点登录的是什么了,但是实习 ...

  10. top命令查看线程信息和jstack使用介绍

    top -Hp pid可以查看某个进程的线程信息 -H 显示线程信息,-p指定pid jstack 线程ID 可以查看某个线程的堆栈情况,特别对于hung挂死的线程,可以使用选项-F强制打印dump信 ...