Description

物理学家小C的研究正遇到某个瓶颈。

他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。

我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.

对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.

每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。

但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。

有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。

现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。

Input

第一行一个整数n,表示星系的星球数。

接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。

接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.

接下来一行一个整数m,表示事件的总数。

事件分为以下三种类型。

(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.

(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.

(3)"F pi qi"表示星球pi能量激发,常数为qi.

Output

对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。

这个应该是伪 $ETT$,不知道真正的 $ETT$ 该咋写.

开始卡了半天常数,本地 $25s$,交上去却一顿 T,后来改用结构体存变量就跑的飞快.

以后写数据结构就都用结构体存了

#include <cstdio>
#include <algorithm> E
#define N 200005
#define ll long long
#define lson t[x].ch[0]
#define rson t[x].ch[1]
#define setIO(s) freopen(s".in", "r", stdin)
using namespace std;
int edges, tim, root = 0, top;
int sta[N], hd[N], to[N], nex[N], L[N], R[N], euler[N], val[N];
inline void addedge(int u, int v)
{
nex[++edges] = hd[u], hd[u] = edges, to[edges] = v;
}
struct Stack
{
int x, i;
Stack(int x = 0, int i = 0) : x(x), i(i) {}
}A[N];
struct Node
{
int siz, d, ch[2], f;
ll sum, val, lazy;
}t[N];
inline int get(int x)
{
return t[t[x].f].ch[1] == x;
}
inline void pushup(int x)
{
t[x].siz = t[lson].siz + t[rson].siz + t[x].d;
t[x].sum = t[lson].sum + t[rson].sum + t[x].val;
}
inline void mark(int x, ll v)
{
t[x].val += 1ll * t[x].d * v;
t[x].sum += 1ll * t[x].siz * v;
t[x].lazy += v;
}
inline void pushdown(int x)
{
if(t[x].lazy)
{
if(lson) mark(lson, t[x].lazy);
if(rson) mark(rson, t[x].lazy);
t[x].lazy = 0;
}
}
inline void rotate(int x)
{
int old = t[x].f, fold = t[old].f, which = get(x);
t[old].ch[which] = t[x].ch[which ^ 1], t[t[old].ch[which]].f = old;
t[x].ch[which ^ 1] = old, t[old].f = x, t[x].f = fold;
if(fold) t[fold].ch[t[fold].ch[1] == old] = x;
pushup(old), pushup(x);
}
inline void splay(int x, int &tar)
{
int u = t[tar].f, v = 0;
for(int g = x ; g ; sta[++v] = g, g = t[g].f);
for(int i = v ; i >= 1; --i) pushdown(sta[i]);
for(int fa; (fa = t[x].f) ^ u; rotate(x))
if(t[fa].f ^ u)
rotate(get(fa) == get(x) ? fa: x);
tar = x;
}
void solve()
{
top = 0;
A[++ top] = Stack(1, hd[1]), L[1] = ++tim, t[tim].d = 1, t[tim].val = (ll) val[1];
for( ; top ; )
{
Stack u = A[top];
if(u.i)
{
A[top].i = nex[A[top].i];
A[++ top] = Stack(to[u.i], hd[to[u.i]]);
L[to[u.i]] = ++tim;
t[tim].d = 1, t[tim].val = (ll) val[to[u.i]];
}
else
{
R[u.x] = ++tim;
t[tim].d = -1, t[tim].val = (ll) -val[u.x];
-- top;
}
}
}
int build(int l, int r, int ff)
{
int mid = (l + r) >> 1;
t[mid].f = ff;
if(mid > l) t[mid].ch[0] = build(l, mid - 1, mid);
if(r > mid) t[mid].ch[1] = build(mid + 1, r, mid);
if(mid == 1) t[mid].ch[0] = tim + 1, t[tim + 1].f = mid;
if(mid == tim) t[mid].ch[1] = tim + 2, t[tim + 2].f = mid;
pushup(mid);
return mid;
}
int pre(int x)
{
int g = root;
splay(x, root);
for(x = lson; rson ; pushdown(x), x = rson);
splay(g, root);
return x;
}
int nxt(int x)
{
int g = root;
splay(x, root);
for(x = rson; lson ; pushdown(x), x = lson);
splay(g, root);
return x;
}
int main()
{
// setIO("input");
int n, m, i, j, x, y;
scanf("%d", &n);
for(i = 2; i <= n ; ++i) scanf("%d", &x), addedge(x, i);
for(i = 1; i <= n ; ++i) scanf("%d", &val[i]);
solve(), root = build(1, tim , 0);
scanf("%d", &m);
for(int cas = 1; cas <= m; ++cas)
{
char str[4];
scanf("%s", str);
if(str[0] == 'Q')
{
scanf("%d", &x), splay(L[x], root), printf("%lld\n", t[root].sum - t[t[root].ch[1]].sum);
}
if(str[0] == 'C')
{
scanf("%d%d", &x, &y);
int l = pre(L[x]), r = nxt(R[x]), key, k;
splay(l, root), splay(r, t[root].ch[1]), key = t[t[root].ch[1]].ch[0];
t[key].f = t[t[root].ch[1]].ch[0] = 0, pushup(t[root].ch[1]), pushup(root);
splay(L[y], root), splay(nxt(L[y]), t[root].ch[1]);
t[t[root].ch[1]].ch[0] = key, t[key].f = t[root].ch[1], pushup(t[root].ch[1]), pushup(root);
}
if(str[0] == 'F')
{
scanf("%d%d", &x, &y);
splay(pre(L[x]), root), splay(nxt(R[x]), t[root].ch[1]);
int key = t[t[root].ch[1]].ch[0];
mark(key, 1ll * y);
}
}
return 0;
}

  

递归:

#include <cstdio>
#include <algorithm>
#define N 200005
#define ll long long
#define lson t[x].ch[0]
#define rson t[x].ch[1]
#define setIO(s) freopen(s".in", "r", stdin)
using namespace std;
int edges, tim, root = 0;
int sta[N], hd[N], to[N], nex[N], L[N], R[N], euler[N], val[N];
inline void addedge(int u, int v)
{
nex[++edges] = hd[u], hd[u] = edges, to[edges] = v;
}
struct Node
{
int siz, d, ch[2], f;
ll sum, val, lazy;
}t[N];
inline int get(int x)
{
return t[t[x].f].ch[1] == x;
}
inline void pushup(int x)
{
t[x].siz = t[lson].siz + t[rson].siz + t[x].d;
t[x].sum = t[lson].sum + t[rson].sum + t[x].val;
}
inline void mark(int x, ll v)
{
t[x].val += 1ll * t[x].d * v;
t[x].sum += 1ll * t[x].siz * v;
t[x].lazy += v;
}
inline void pushdown(int x)
{
if(t[x].lazy)
{
if(lson) mark(lson, t[x].lazy);
if(rson) mark(rson, t[x].lazy);
t[x].lazy = 0;
}
}
inline void rotate(int x)
{
int old = t[x].f, fold = t[old].f, which = get(x);
t[old].ch[which] = t[x].ch[which ^ 1], t[t[old].ch[which]].f = old;
t[x].ch[which ^ 1] = old, t[old].f = x, t[x].f = fold;
if(fold) t[fold].ch[t[fold].ch[1] == old] = x;
pushup(old), pushup(x);
}
inline void splay(int x, int &tar)
{
int u = t[tar].f, v = 0;
for(int g = x ; g ; sta[++v] = g, g = t[g].f);
for(int i = v ; i >= 1; --i) pushdown(sta[i]);
for(int fa; (fa = t[x].f) ^ u; rotate(x))
if(t[fa].f ^ u)
rotate(get(fa) == get(x) ? fa: x);
tar = x;
}
void dfs(int u)
{
L[u] = ++tim;
t[tim].d = 1, t[tim].val = (ll)val[u];
for(int i = hd[u] ; i ; i = nex[i]) dfs(to[i]);
R[u] = ++tim;
t[tim].d = -1, t[tim].val = (ll)-val[u];
}
int build(int l, int r, int ff)
{
int mid = (l + r) >> 1;
t[mid].f = ff;
if(mid > l) t[mid].ch[0] = build(l, mid - 1, mid);
if(r > mid) t[mid].ch[1] = build(mid + 1, r, mid);
if(mid == 1) t[mid].ch[0] = tim + 1, t[tim + 1].f = mid;
if(mid == tim) t[mid].ch[1] = tim + 2, t[tim + 2].f = mid;
pushup(mid);
// printf("%d %d %d\n",mid, t[mid].ch[0], t[mid].ch[1]);
return mid;
}
int pre(int x)
{
int g = root;
splay(x, root);
for(x = lson; rson ; pushdown(x), x = rson);
splay(g, root);
return x;
}
int nxt(int x)
{
int g = root;
splay(x, root);
for(x = rson; lson ; pushdown(x), x = lson);
splay(g, root);
return x;
}
int main()
{
// setIO("input");
int n, m, i, j, x, y;
scanf("%d", &n);
for(i = 2; i <= n ; ++i) scanf("%d", &x), addedge(x, i);
for(i = 1; i <= n ; ++i) scanf("%d", &val[i]);
dfs(1), root = build(1, tim , 0);
scanf("%d", &m);
for(int cas = 1; cas <= m; ++cas)
{
char str[4];
scanf("%s", str);
if(str[0] == 'Q')
{
scanf("%d", &x), splay(L[x], root), printf("%lld\n", t[root].sum - t[t[root].ch[1]].sum);
}
if(str[0] == 'C')
{
scanf("%d%d", &x, &y);
int l = pre(L[x]), r = nxt(R[x]), key, k;
splay(l, root), splay(r, t[root].ch[1]), key = t[t[root].ch[1]].ch[0];
t[key].f = t[t[root].ch[1]].ch[0] = 0, pushup(t[root].ch[1]), pushup(root);
splay(L[y], root), splay(nxt(L[y]), t[root].ch[1]);
t[t[root].ch[1]].ch[0] = key, t[key].f = t[root].ch[1], pushup(t[root].ch[1]), pushup(root);
}
if(str[0] == 'F')
{
scanf("%d%d", &x, &y);
splay(pre(L[x]), root), splay(nxt(R[x]), t[root].ch[1]);
int key = t[t[root].ch[1]].ch[0];
mark(key, 1ll * y);
}
}
return 0;
}

  

BZOJ 3786: 星系探索 ETT的更多相关文章

  1. BZOJ 3786: 星系探索 解题报告

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

  2. bzoj 3786 星系探索 dfs+splay

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

  3. BZOJ 3786: 星系探索 [伪ETT]

    传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...

  4. BZOJ 3786 星系探索

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

  5. BZOJ 3786 星系探索 ——Splay

    子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...

  6. BZOJ 3786 星系探索 (splay+dfs序)

    题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...

  7. BZOJ 3786: 星系探索 欧拉游览树

    一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序 #include <cstring> #include <algorithm> ...

  8. 【BZOJ】3786: 星系探索

    [题意]给定一棵带点权树,三种操作: 1.询问点x到根的路径和 2.子树x内的点权加定值y 3.将点x的父亲更换为y,保证仍是树. [算法]平衡树(fhq-treap) [题解] 将树的dfs序作为序 ...

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

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

随机推荐

  1. centos7 中如何查看、打开、关闭防火墙。

    首先是看centos7的防火墙的状态,查看的命令为: sudo systemctl status firewalld. 查看后,看到active(running)就意味着防火墙打开了, 如果想关闭防火 ...

  2. python 传址 与传值(暂时保存,后续做分类)

    # python 传址 与 传值 # 定义一个函数 用于将 list 下标为2的数据加100 并进行打印 该list def test1(list): list[2]+=100 print(list) ...

  3. Luogu P2915 [USACO08NOV]奶牛混合起来

    题外话: 是非常颓废的博主 写题解也不在于能不能通过啦,主要是缓解颓废 首先看到这个题,肯定是可以暴力搜索的: 不得不说这道题还是很善良的,一波大暴力dfs,居然有70pts: #include< ...

  4. tf-图像预处理

    tensorflow 中自带了很多图像处理的方法,基本都在 tf.image 模块中,虽然不如 opencv 强大,但也比较常用,这里做个记录. 图像编解码 1. 用 tf 的方法读取图片后,都需要进 ...

  5. numpy-数据格式之 int 与 uint

    概念 整型分为 有符号整型 和 无符号整型,其区别在于 无符号整型 可以存放的正数范围 比 有符号整型 大一倍,因为 有符号整型  将最高位存储符号,而 无符号整型 全部存储数字 # 1 111000 ...

  6. 解决IOS把数字渲染为电话号码,颜色为蓝色解决方案

    可将telephone=no,则手机号码不被显示为拨号链接<meta name="format-detection" content="telephone=no&q ...

  7. thinkphp5 安装

    thinkphp 5开始可以使用composer安装 所以在安装thinkphp5.1之前,我们先安装composer ,下载地址:https://www.phpcomposer.com/ 安装完co ...

  8. 使用T4模板为EF框架添加数据库实体注释(转)

    1. 下载文件GetSummery.ttinclude2. 把我们下载下来的文件解压,将解压出来的文件放入解决方案中3. 修改下app.config,添加一个连接字符串: <add name=& ...

  9. Genymotion模拟器使用camera

    1.前言 最近开发react-native的app,上传图片功能需要使用相机,发现Genymotion默认的相机不工作.查看同行的博客解决了,归纳整理一下. 2.步骤 2.1安装Genymotion: ...

  10. init_module - 初始化一条可加载模块的记录.

    总览 #include <linux/module.h> int init_module(const char *name, struct module *image); 描述 init_ ...