BZOJ3786:星系探索(Splay,括号序)
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的事件,输出一行一个整数,表示此次实验的收集器最终能量。
Sample Input
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
Sample Output
15
25
HINT
n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保证操作合法。注意w_i>=0
Solution
TMD卡了半天常没卡过去自闭了……
感觉这个题还是很巧妙的。先说下什么是括号序:$DFS$的时候进入一个点将点入队,出这个点的时候再将这个点入队,这个队列就是欧拉序。
所以这个应该怎么做呢?
第一个操作就是根的入队节点到查询的点的入队节点这一段区间的权值和。
第二个操作就是将一个点的入队到出队节点这一段区间(也就是这个点的子树)移动。
第三个操作就是区间打标记……没什么好说的。
$pushdown$的时候需要记录一下这个区间内有几个入队节点几个出队节点再更新。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (200009)
#define LL long long
using namespace std; struct Edge{int to,next;}edge[N<<];
int n,m,x,y,Root,q[N],q_num;
int head[N],num_edge;
int Son[N][],Father[N];
int a[N],Flag[N];
LL Num[N],Sum[N],Val[N],Add[N];
char opt; inline int read()
{
int x=; char c=getchar();
while (c<'' || c>'') c=getchar();
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x;
} void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} int Get(int x) {return Son[Father[x]][]==x;} void Pushup(int x)
{
Num[x]=Num[Son[x][]]+Num[Son[x][]]+Flag[x];
Sum[x]=Sum[Son[x][]]+Sum[Son[x][]]+Val[x];
} void Pushdown(int x)
{
if (Add[x])
{
int ls=Son[x][], rs=Son[x][];
Sum[ls]+=Add[x]*Num[ls];
Val[ls]+=Flag[ls]*Add[x]; Add[ls]+=Add[x];
Sum[rs]+=Add[x]*Num[rs];
Val[rs]+=Flag[rs]*Add[x]; Add[rs]+=Add[x];
Add[x]=;
}
} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
Pushdown(fa); Pushdown(x);
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Son[fa][wh]=Son[x][wh^]; Father[fa]=x;
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Son[x][wh^]=fa; Father[x]=fafa;
Pushup(fa); Pushup(x);
} void Splay(int x,int tar)
{
for (int fa; (fa=Father[x])!=tar; Rotate(x))
if (Father[fa]!=tar)
Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
} int Pre(int x)
{
Splay(x,);
int now=Son[x][];
while (Son[now][]) now=Son[now][];
return now;
} int Next(int x)
{
Splay(x,);
int now=Son[x][];
while (Son[now][]) now=Son[now][];
return now;
} void Query(int x)
{
int pre=n<<|, nxt=Next(x);
Splay(pre,);
Splay(nxt,pre);
printf("%lld\n",Sum[Son[nxt][]]);
} void Change(int x,int y)
{
int pre=Pre(x),nxt=Next(x+n);
Splay(pre,); Splay(nxt,pre);
int tmp=Son[nxt][];
Father[Son[nxt][]]=; Son[nxt][]=;
Pushup(Son[Root][]); Pushup(Root); int Nxt=Next(y);
Splay(y,); Splay(Nxt,y);
Father[tmp]=Nxt; Son[Nxt][]=tmp;
Pushup(Son[Root][]); Pushup(Root);
} void Update(int x,int y)
{
int pre=Pre(x), nxt=Next(x+n);
Splay(pre,); Splay(nxt,pre);
int tmp=Son[nxt][];
Add[tmp]+=y;
Sum[tmp]+=Add[tmp]*Num[tmp];
Val[tmp]+=Flag[tmp]*Add[tmp];
} void DFS(int x,int fa)
{
q[++q_num]=x;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa) DFS(edge[i].to,x);
q[++q_num]=x+n;
} int Build(int l,int r,int fa)
{
if (l>r) {return ;}
int mid=(l+r)>>, now=q[mid];
Father[now]=fa;
Son[now][]=Build(l,mid-,now);
Son[now][]=Build(mid+,r,now);
Val[now]=(now<=n)?a[now]:-a[now-n];
Pushup(now); return now;
} int main()
{
n=read();
for (int i=; i<=n; ++i)
x=read(), add(x,i);
for (int i=; i<=n; ++i)
a[i]=read(), Flag[i]=, Flag[i+n]=-;
q[q_num=]=n<<|;
DFS(,);
q[++q_num]=n+<<;
Root=Build(,q_num,);
m=read();
for (int i=; i<=m; ++i)
{
opt=getchar(); while (opt<'A' || opt>'Z') opt=getchar();
if (opt=='Q') x=read(), Query(x);
if (opt=='C') x=read(), y=read(), Change(x,y);
if (opt=='F') x=read(), y=read(), Update(x,y);
}
}
BZOJ3786:星系探索(Splay,括号序)的更多相关文章
- BZOJ3786: 星系探索 Splay+DFS序
题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...
- [BZOJ3786] 星系探索(括号序列+Splay)
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 2191 Solved: 644[Submit][Status][Discuss ...
- 【BZOJ-3786】星系探索 Splay + DFS序
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 647 Solved: 212[Submit][Status][Discuss] ...
- bzoj3786星系探索 splay
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1314 Solved: 425[Submit][Status][Discuss ...
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- bzoj3786 星际探索 splay dfs序
这道题 首先 因为他求的是当前点到根节点的路径和 我们可以将题目转换为括号序列的写法 将点拆为左括号以及右括号 左括号为正 右括号为负 这样题目就变为了求前缀和了 如果一个点是这个点的子树 那么他的左 ...
- BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...
- BZOJ3786 星系探索 【Splay维护dfs序】*
BZOJ3786 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均 ...
- [BZOJ3786]星系探索
[BZOJ3786]星系探索 试题描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个 ...
随机推荐
- Caused by: org.hibernate.HibernateException: identifier of an instance of ... is alterde from
Caused by: org.hibernate.HibernateException: identifier of an instance of ... is alterde from Hi ...
- PHP · MySQL函数
连接名=mysql_connect("主机","用户名","密码"); 连接名=mysql_qconnect("主机", ...
- Eclipse的版本命名
Eclipse自3.1开始使用木星的卫星作为版本名,例如: 木卫一:伊奥 lo木卫二:欧罗巴 Europa木卫三:伽倪墨得斯 Ganymede木卫四:卡利斯托 Callisto .... Eclips ...
- Mybatis源代码分析之parsing包
parsing,从字面上理解就是编译解析的意思,那么这个包中的内容就应该和mybatis配置文件的编译解析有关系.本文首先会按照引用层次来分别介绍这个包中各个类的作用,而后再用实际的例子解释它们是如何 ...
- Cocoa pod导入第三方框架遇到的那点事儿
废话不多说,直接上干货. 以下所有操作均是在Cocoapod导入第三方库,并且是.xcworkspace的工程里面操作的, 1.导入头文件找不到,也就是所谓的,not find ''AFNetwork ...
- java工程师_基础_阶段一_HTML笔记篇
一.了解HTML语言 html:超文本标记语言. 二.HTML整体结构<html> <head> </head> <body> </body> ...
- 新浪微博开放平台账号申请(基于dcloud开发)
注意事项: 1.新浪微博不仅需要appkey和appsecret,而且还需要回调的url,这个链接是可以随便写的,但是需要和在开放平台申请的一致. 2. Android签名包信息部分 (1.)首先安卓 ...
- L1 Cache, L2 Cache读取命中率与时钟周期计算
CPU在Cache中找到有用的数据被称为命中,当Cache中没有CPU所需的数据时(这时称为未命中),CPU才访问内存.从理论上讲,在一颗拥有2级Cache的CPU中,读取L1 Cache的命中率为8 ...
- Windows win7下VMware Virtual Ethernet Adapter未识别网络解决方法
win7下VMware Virtual Ethernet Adapter未识别网络解决方法[摘] by:授客 QQ:1033553122 问题描述 win7系统下安装VMware,查看网卡适配器设置, ...
- Android MVP开发模式及Retrofit + RxJava封装
代码已上传到Github,因为接口都是模拟无法进行测试,明白大概的逻辑就行了! 欢迎浏览我的博客--https://pushy.site 1. MVP模式 1.1 介绍 如果熟悉MVP模式架构的话,对 ...