3786: 星系探索

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 2191  Solved: 644
[Submit][Status][Discuss]

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

3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2

Sample Output

9
15
25

HINT

n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保证操作合法。注意w_i>=0

Solution

   这是jly dalao课上讲过的例题,所以我下来实现一下。

  考虑维护原树的括号序列,设一个节点x的进入和离开的时间戳为l[x]和r[x],那么对于

  操作C:把x的父亲节点变为y,相当于把区间[l[x],r[x]]插入到l[y]之后;

  操作Q:查询节点x到根的路径的权值和,相当于查询区间[l[1],l[x]]中所有只出现了一次的节点的权值和,因为显然在括号序列中一个位置p的前缀中所有只出现了一次的节点就是它的所有祖先

  操作F:把x的子树整体加v,相当于区间[l[x],r[x]]整体加v。

  所以用一个Splay维护括号序列,支持区间删除插入、区间加和区间查询就可以了。

  但还有一个问题:如何实现只查询出现了一次的节点的权值和?

  对每个节点x的l[x]打上正标记,r[x]打上负标记即可。

  注意这题要开longlong,括号序列长度为2*n不用我说吧,并且有点卡时(看看时限就懂了),请使用较优秀的IO并且不要用STL。。。

  写给自己的调Splay的注意事项:

  1. Splay的基本结构:检查父子关系是否成功构建,是否赋初值,sz值是否正常。(RE)
  2. pushdown是写在kth还是splay中:如果是后者,需要用一个把祖先push进去,然后一个个pushdown。
  3. 检查pushup和change_val是否写对:这一点要根据具体题目要维护的信息。(WA)

  这题码了0.5h,然后其实只有两个很小的错误,一个在第一步中de了0.5h,另一个在第三步de了10min,还要加油啊。  

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+,INF=0x3f3f3f3f;
inline int read(){
int x=,w=;char ch=;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<)+(x<<)+(ch^),ch=getchar();
return w?-x:x;
}
bool b[N<<];
int n,m,idx,l[N],r[N],a[N<<],w[N],st[N<<],tp;
vector<int> to[N];
void dfs(int x){
l[x]=++idx;a[idx]=w[x];b[idx]=;
for(int i=;i<to[x].size();++i) dfs(to[x][i]);
r[x]=++idx;a[idx]=-w[x];b[idx]=;
}
struct Splay{
struct Node{
int fa,ch[];
bool fg;
LL val,add,sum,c1,c2;//c1:fg为0的节点数 c2:fg为1的节点数
Node(){}
Node(int a,int b,int f,int c,bool d):fa(f),val(c),fg(d){ch[]=a,ch[]=b;c1=c2=add=sum=;}
}t[N<<];
int rt;
int get(int x){return x==t[t[x].fa].ch[];}
void link(int x,int y,int d){t[x].ch[d]=y;t[y].fa=x;}
void change_val(int x,LL v){
t[x].val+=t[x].fg?-v:v;
t[x].sum+=(t[x].c1-t[x].c2)*v;
t[x].add+=v;
}
void pushup(int x){
int &l=t[x].ch[],&r=t[x].ch[];
t[x].sum=t[l].sum+t[r].sum+t[x].val;
t[x].c1=t[l].c1+t[r].c1+(t[x].fg==);
t[x].c2=t[l].c2+t[r].c2+(t[x].fg==);
}
void pushdown(int x){
if(t[x].add){
change_val(t[x].ch[],t[x].add);
change_val(t[x].ch[],t[x].add);
t[x].add=;
}
}
void rotate(int x){
int d=get(x),f=t[x].fa,ff=t[f].fa;
link(ff,x,get(f));
link(f,t[x].ch[d^],d);
link(x,f,d^);
pushup(f),pushup(x);
}
void splay(int x,int goal){
tp=;
for(int i=x;i;i=t[i].fa) st[++tp]=i;
while(tp) pushdown(st[tp--]);
for(;t[x].fa^goal;rotate(x)){
int f=t[x].fa,ff=t[f].fa;
if(ff^goal) get(x)^get(f)?rotate(x):rotate(f);
}
if(!goal) rt=x;
}
int build(int l,int r,int f){
if(l>r) return ;
int mid=l+r>>;
t[mid]=Node(build(l,mid-,mid),build(mid+,r,mid),f,a[mid],b[mid]);
pushup(mid);
return mid;
}
int next(int x,int d){
splay(x,);
x=t[x].ch[d];
while(t[x].ch[d^]) x=t[x].ch[d^];
return x;
}
int split(int i,int j){
splay(i,),splay(j,i);return t[j].ch[];
}
void update(int a,int v){
int i=next(l[a],),j=next(r[a],);
int x=split(i,j);
change_val(x,v);
pushup(j),pushup(i);
}
void change(int a,int b){
int i=next(l[a],),j=next(r[a],);
int x=split(i,j);
t[j].ch[]=;
pushup(j),pushup(i);
i=l[b],j=next(l[b],);
split(i,j);
link(j,x,);
pushup(j),pushup(i);
}
LL query(int a){
return t[split(next(l[],),next(l[a],))].sum;
}
}T;
int main(){
n=read();
for(int i=;i<=n;++i) to[read()].push_back(i);
for(int i=;i<=n;++i) w[i]=read();
a[++idx]=; //哨兵的b值没有影响
dfs();
a[++idx]=;
T.rt=T.build(,n*+,);
char ch[];
m=read();
while(m--){
scanf("%s",ch);int x=read();
if(ch[]=='Q') printf("%lld\n",T.query(x));
else if(ch[]=='C') T.change(x,read());
else T.update(x,read());
}
return ;
}

BZOJ3786

[BZOJ3786] 星系探索(括号序列+Splay)的更多相关文章

  1. BZOJ3786 星系探索 【Splay维护dfs序】*

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

  2. [BZOJ3786]星系探索

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

  3. bzoj3786星系探索 splay

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

  4. 【BZOJ3786】星系探索 DFS序+Splay

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

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

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

  6. bzoj 2209: [Jsoi2011]括号序列 splay

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 833  Solved: 392[Submit][Status ...

  7. BZOJ 2209: [Jsoi2011]括号序列 [splay 括号]

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1111  Solved: 541[Submit][Statu ...

  8. 【BZOJ-2329&2209】括号修复&括号序列 Splay

    2329: [HNOI2011]括号修复 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1007  Solved: 476[Submit][Statu ...

  9. 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay

    [BZOJ2329/2209][HNOI2011]括号修复/[Jsoi2011]括号序列 题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作, ...

随机推荐

  1. mysql 相关文章

    <58到家MySQL军规升级版> <数据库索引,到底是什么做的?> <MyISAM与InnoDB的索引差异究竟是啥?> <InnoDB,为何并发如此之高?&g ...

  2. 如何将本地的项目推送至git仓库

    转载:https://www.jianshu.com/p/31dea20b0084 1.cd projectName probjectName是项目文件夹的名字, 先进入项目文件夹 2.git ini ...

  3. 常用Java字段的正则校验

    正则表达式: 单个字符的匹配规则如下: 多个字符的匹配规则如下: 复杂匹配规则主要有: 常用正则表达式校验规则: 一.校验数字的表达式 1.数字:^[0-9]*$ 2.n位的数字:^\d{n}$ 3. ...

  4. Hive编程指南读书笔记(1):

    1.Mapreduce是一种计算模型,将计算任务分割成多个可以在服务器集群中并行执行的任务,然后分散到一群家用的或者服务器级别的硬件机器上,从而降低成本并提供水平可伸缩性. 2.mapreduce的两 ...

  5. vue高亮一级、二级导航

    使用vue开发过程中有的项目会存在多级导航的情况,如下图,这种就存在了两层,那么该如何高亮一级导航,又该如何高亮二级导航这就是今天我要记录的内容. 1.高亮一级导航很简单,代码如下: // 点击一级导 ...

  6. 使用maven构建dubbo服务的可执行jar包+Dubbo 程序实例

    https://blog.csdn.net/zsg88/article/details/76100482 https://blog.csdn.net/zsg88/article/details/762 ...

  7. 记一次生产环境presto删表失败的问题

    场景,开发用java程序连接presto创建一个表,这个表在hdfs的权限为: 然后用presto去删除这个表 报错,没有权限删除,查看上一级目录权限,发现权限正常 直连hive删表 发现正常. 然后 ...

  8. 基于Zabbix 3.2.6版本的low-level-discover(lld)

    个人使用理解:      1.使用一个返回值是JSON的KEY,在Templates或者Hosts中创建一个Discovery规则.该key的返回值类似于: 索引key -- value 类型     ...

  9. Ubuntu中用bitbake core-image-minimal时,出错:from bb import data

    问题描述: 在准备ARM交叉编译环境时,执行完命令: DISTRO=fsl-imx-x11 MACHINE=imx6qsabresd source fsl-setup-release.sh -b bu ...

  10. height 自适应问题

    何为高度自适应? 高度自适应就是高度能跟随浏览器窗口的大小改变而改变,典型的运用在一些后台界面中上面一栏高度固定用作菜单栏或导航栏,下面一栏高度自适应用于显示内容.高度自适应不像宽度自适应那样简单,在 ...