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号星球),其余的所有星球均有且仅有一个 ...
随机推荐
- CentOS6.8启动Tomcat无法访问
今天笔者在CentOS6.8的生产环境上配置Java环境,安装JDK,部署Tomcat,这本来是很简单的一件事,可是最后发现通过IP一直访问不了Tomcat的默认页面. 图1. 无法访问Tomcat默 ...
- 关于Java中语句符号及格式的理解
关于Java中语句符号及格式的理解 这篇文章是撰写的第一篇文章,在此作一下博主是一名在读的工科研究生,种种原因,研二开始决定转行从事程序员工作.开始的自学之路并不算非常顺畅,也走了一点弯路,但一直都坚 ...
- Tomcat配置JVM参数步骤
这里向大家描述一下如何使用Tomcat配置JVM参数,Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机.您可以选择自己的需要选择不同的操作系统和对应的JDK ...
- MS SQL Server数据库在线管理工具
MS SQL Server数据库以其优异的性能,被广泛使用,特别是政务,医疗行业.但是远程维护挺不方便的,目前有一款基于WEB的工具TreeSoft数据库管理系统. 免安装,直接解压就可以用了.直接通 ...
- 修改request请求参数
本质上来讲,request请求当中的参数是无法更改的,也不能添加或者删除: 但在后台程序中,一般对request的参数的操作,都是通过request的getParameter.getParameter ...
- 各种IDE的使用
sharpdevelop http://blog.sina.com.cn/s/blog_d1001bff0101di7p.html
- 微软正式开源Blazor,将.NET带回到浏览器
微软 ASP.NET 团队近日正式开源了Blazor,这是一个Web UI框架,可通过WebAssembly在任意浏览器中运行 .Net. Blazor旨在简化快速的单页面 .Net 浏览器应用的构建 ...
- spring AOP 动态代理和静态代理以及事务
AOP(Aspect Oriented Programming),即面向切面编程 AOP技术,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装 ...
- 简单的PHP的任务队列
文章太长,不作过多介绍,反正,文章的头部就说明了大概的意思...原文如下:写了一个简单的队列任务处理.多进程任务,异步任务可能会用到这个(主要是命令行应用)比如,任务的某个一个环节速度十分不稳定,可能 ...
- mysql 的varchar类型小记
参考链接:MySQL的varchar长度问题 今天用mysql做一个demo,创建了个表: -- 借款表 CREATE TABLE jk ( id ) NOT NULL auto_increment, ...