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. 19Spring返回通知&异常通知&环绕通知

    在前置通知和后置通知的基础上加上返回通知&异常通知&环绕通知 代码: package com.cn.spring.aop.impl; //加减乘除的接口类 public interfa ...

  2. Direct3D 12 创建windows窗口

    之前列出了计算机图形学的计划,现在开始这一阶段的学习,首先是Windows窗口的创建. 创建windows窗口 环境: 1. Visual Studio 2015 新建项目 创建工程项目完成,确定为窗 ...

  3. tarjan 割点 割边

    by   GeneralLiu tarjan 求 割点 割边 无向图  的 割点 割边: 对于无向连通图来说, 如果删除   一个点以及与它相连的边   之后, 使得这个图不连通, 那么该点为割点 : ...

  4. 【ZJOI2017 Round1练习&BZOJ5350】D5T1 masodik(DP,斜率优化)

    题意:你要从(0,0)点走到(n,m), 每次只能往 x 轴或者 y 轴正方向移动一个单位距离.从(i,j)移动到(i,j+1)的代价为 ri,从(i,j)移动到(i+1,j)的代价为 cj. 求最小 ...

  5. vim状态栏的扩充

    将以下内容添加到~/.vimrc文件中: set statusline= set statusline+=%7*\[%n]                                  " ...

  6. jquery控制Request Payload和Form Data

    Request Payload方式,会发起两次请求 Form Data只发起一次请求 若要把一个ajax请求改为Payload方式,设置contentType即可,发现请求参数不是对象,再把参数转换为 ...

  7. cogs——555. 网络探测

    555. 网络探测 ★☆   输入文件:ping.in   输出文件:ping.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述]    当出现网络故障时,我们经常使用“p ...

  8. Java内存分配与参数传递

    JAVA中方法的参数传递方式只有一种:值传递. JAVA内存分配: 1.栈:存放 基本类型的数据.对象的引用(类似于C语言中的指针) 2.堆:存放用new产生的数据 3.静态域:存放在对象中用stat ...

  9. Visual studio 2008 的语法高亮插件 WordLight

    前段时间一直在使用matlab,今天需要使用vs2008,而用惯了matlab,习惯了其中一项选中变量高亮的设置,突然回来使用VS,感到各种不适应,顿时想到了一个词:矫情 呵呵,于是在网上找各种插件, ...

  10. delphi的一些语法知识 以及参数传递问题,按引用方式传递参数,按值方式传递参数

    //delphi中exit,abort,break,continue 的区别 exit: 退出函数体abort: 遇到异常,安静处理,就是不显示不提示break: 退出当前循环体,包括for ,whi ...