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号星球),其余的所有星球均有且仅有一个 ...
随机推荐
- Android Studio 3.0找不到Android Device Monitor
因为自Android Studio 3.0开始弃用Android Device Monitor,Android Developers官网上的原话是: Android Device Monitor is ...
- [日常] crontab的秒执行和串行化和多进程实现
1. crontab的最低运行频率是,按照每分钟执行一次,通过在脚本中简单实现按秒级别运行 比如这条cron规则 , 每分钟执行一次脚本 * * * * * php /var/www/html/tes ...
- Linux root用户不能通过SSH连接的问题
http://jingyan.baidu.com/article/fd8044fad48fc95031137a85.html 最近在虚拟机安装Ubuntu之后,通过普通ssh远程连接的时候明明输入了正 ...
- 前端(十):使用redux管理数据
react本身能够完成动态数据的监听和更新,如果不是必要可以不适用redux. 安装redux: cnpm install redux --save,或者yarn add redux. 一.react ...
- 思维导图(JavaScript基础)——温习一下下
- Stream grouping-storm的流分组策略
A stream grouping tells a topology how to send tuples between two components. Remember, spouts and b ...
- jQuery实现的上下滚动公告栏详细讲解
之前做项目的时候,一直都想着做一个上下滚动的公告栏,作为展示网站的最新公告信息,因为刚开始自己的思路并不是太清晰,在网上找了很多的源码,但是却发现都不能让自己满意,有的还会出现一些小问题,比如,有时候 ...
- 《css揭秘》下(伪元素,文字背景,垂直居中技巧,文字环绕)
本篇主要记录<CSS3揭秘>一书中后面几章的常用技巧. 1.伪元素换行 先看下HTML代码,如下 <div class="demo1"> <div c ...
- CSS选择器之伪类选择器(伪元素)
selection [CSS4]应用于文档中被用户高亮的部分(比如使用鼠标或其他选择设备选中的部分).(IE8及以下不支持)(火狐-moz-selection) first-line 选择每个 < ...
- Android 蓝牙开发之搜索、配对、连接、通信大全
蓝牙( Bluetooth®):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据 交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙设备最 ...