bzoj 3786 星系探索 dfs+splay
【BZOJ3786】星系探索
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.保证操作合法。
题意:给出一棵树,要求有以下这些操作:
1.求出一个节点到根的点权和。
2.将一个节点的父亲改变。
3.将一个子树中的每一个节点都加上一个权值
题解:主要是操作2,不然树链剖分可以强艹过,所以splay+dfs序即可。
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<map>
#include<queue>
#include<vector>
#include<cstdlib>
#include<ctime> #define ll long long
#define N 200007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,q;
int rt,top,tot;
int a[N],sta[N],fa[N],w[N],v[N],tag[N];
int c[N][],t[N][],s[N][];
int cnt,head[N],next[N],rea[N];
ll sum[N]; void add(int u,int v)
{
next[++cnt]=head[u];
head[u]=cnt;
rea[cnt]=v;
}
void dfs(int u)
{
v[t[u][]=++tot]=a[u],w[tot]=;
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (!t[v][])
dfs(v);
}
v[t[u][]=++tot]=-a[u],w[tot]=-;
}
inline void pushup(int p)
{
if (!p) return;
int l=c[p][],r=c[p][];
s[p][]=s[l][]+s[r][]+(w[p]==);
s[p][]=s[l][]+s[r][]+(w[p]==-);
sum[p]=sum[l]+sum[r]+v[p];
}
inline void update(int p,ll z)
{
if (!p) return;
sum[p]+=(ll)(s[p][]-s[p][])*z;
v[p]+=w[p]*z;
tag[p]+=z;
}
inline void pushdown(int x)
{
if (!x) return;
if (!tag[x]) return;
update(c[x][],tag[x]);
update(c[x][],tag[x]);
tag[x]=;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if (c[y][]==x) l=;else l=;r=l^;
if (y!=k) c[z][c[z][]==y]=x;
else k=x;
fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
c[y][l]=c[x][r],c[x][r]=y;
pushup(x),pushup(y);
}
void splay(int x,int &k)
{
// cout<<" "<<x<<" "<<k<<endl;
for(int i=x;i;i=fa[i]) sta[++top]=i;
while (top) pushdown(sta[top--]);
while(x!=k)
{
//cout<<x<<" "<<k<<endl;
int y=fa[x],z=fa[y];
if (y!=k)
{
if (c[z][]==y^c[y][]==x) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
inline int findmin(int x)
{
while(c[x][])
x=c[x][];
return x;
}
inline int findmax(int x)
{
while(c[x][])
x=c[x][];
return x;
}
void split(int x,int y)
{
splay(x,rt);
int t1=findmax(c[x][]);
splay(y,rt);
int t2=findmin(c[y][]);
splay(t1,rt);
splay(t2,c[t1][]);
}
void build(int l,int r,int f)
{
if (l>r) return;
int x=(l+r)>>;
fa[x]=f;c[f][x>f]=x;
if (l==r)
{
sum[x]=v[x];
s[x][]=w[x]==;
s[x][]=-s[x][];
return;
}
build(l,x-,x);build(x+,r,x);
pushup(x);
}
int main()
{
memset(head,-,sizeof(head));
n=read();
for (int i=;i<=n;i++)
{
int x=read();
add(x,i);
}
for (int i=;i<=n;i++)
a[i]=read();
tot=,dfs();//增加哨兵。
build(,*n+,);
rt=(+*n+)>>; q=read();
while(q--)
{
char ch[];
scanf("%s",ch);
if (ch[]=='Q')
{
int x=read();
splay(t[][],rt);
splay(t[x][],c[rt][]);
printf("%lld\n",sum[c[c[rt][]][]]+(ll)v[rt]+(ll)v[c[rt][]]);
}
else if (ch[]=='F')
{
int x=read(),y=read(),z;
splay(t[x][],rt);splay(t[x][],c[rt][]);
z=c[rt][];
v[rt]+=w[rt]*y;v[z]+=w[z]*y;
update(c[z][],y);
pushup(z);pushup(rt);
}
else
{
int x=read(),y=read(),z,tmp;
split(t[x][],t[x][]);
z=c[rt][];tmp=c[z][];c[z][]=;
pushup(z);pushup(rt);
splay(t[y][],rt);
splay(findmin(c[rt][]),c[rt][]);
z=c[rt][];c[z][]=tmp;fa[tmp]=z;
pushup(z);pushup(rt);
}
}
}
bzoj 3786 星系探索 dfs+splay的更多相关文章
- BZOJ 3786: 星系探索 解题报告
3786: 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅 ...
- BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...
- BZOJ 3786 星系探索 ——Splay
子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...
- BZOJ 3786 星系探索
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3786: 星系探索 ETT
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3786: 星系探索 [伪ETT]
传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...
- BZOJ 3786: 星系探索 欧拉游览树
一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序 #include <cstring> #include <algorithm> ...
- BZOJ3786 星系探索 【Splay维护dfs序】*
BZOJ3786 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均 ...
- 【BZOJ3786】星系探索 DFS序+Splay
[BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...
随机推荐
- MVC:html动态追加行及取值
先一个button id=addRow 点击事件进行添加 $("#addRow").bind("click", function () { var addH ...
- AJPFX关于Timer类的学习
* Timer类:计时器public class Demo1 { public static void main(String[] args) throws InterruptedException ...
- PKU_campus_2018_H Safe Upper Bound
思路: 题目链接http://poj.openjudge.cn/practice/C18H/ 用2147483647除以最大素因子. 这里用了Pollard_rho因子分解算法,模板参考了http:/ ...
- Web前端开发的四个阶段(小白必看)
第一阶段:HTML的学习 超文本标记语言(HyperText Mark-up Language 简称HTML)是一个网页的骨架,无论是静态网页还是动态网页,最终返回到浏览器端的都是HTML代码,浏览器 ...
- 浅析Statement和PreparedStatement的区别
当我们使用java程序来操作sql server时会使用到Statement和PreparedStatement,俩者都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句.那么如何 ...
- 利用JSTL重写查询的jsp页面
利用JSTL重写Java Web MVC实例中的jsp页面 第一步:导入jstl.jar和standard.jar文件
- 使用JavaScript给对象修改注册监听器
我们在开发一些大型前端项目时,会遇到这样一种情况,某个变量上有个字段.我们想知道是哪一段程序修改了这个变量上的字段.比如全局变量window上我们自定义了一个新字段_name,我们想知道到底有哪些程序 ...
- Navicat连不上MySQL的解决办法
USE mysql; ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '{your password}'; ...
- C/C++语言:科学计数法
主要用来表示浮点数,表达方便 浮点数的科学计数,由三个部分组成: a + E + b a:由一个浮点数组成,如果写成整数,编译器会自动转化为浮点数: E:可以大写E,也可以小写e: b:使用一个十进制 ...
- HTML页面中解决内容元素随窗口变化布局变乱问题
1.给body加上一个min-width最小宽度,以px为单位,这样当页面变小时,当达到你所设置的最小宽度,body的宽度不再改变,超出的部分会用横向滚动条显示,其内所有元素的布局也不会受影响. 2. ...