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

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&lt;di,xi&lt;=n,wi,qi&lt;=100000" role="presentation">1<di,xi<=n,wi,qi<=1000001<di,xi<=n,wi,qi<=100000.保证操作合法。注意wi&gt;=0" role="presentation">wi>=0wi>=0


tips:

罪恶的卡常,本机20s-在BZOJ上却要T,BZOJ的评测机是土豆吗??

强烈建议BZOJ把评测机换一换


反正代码是正确的,卡常之类的就不管了吧

首先可以发现这个结构是一个树形结构,然后操作就是查询一个点到根节点的路径权值和,修改一个节点的父亲,还有把一个子树都加上一个值

一开始想玩LCT,但发现LCT维护子树信息好像很困难?

所以转念一想,想到了dfs序的优美性质,这样就可以把求和转化成前缀和,把修改父亲转化成区间平移,把子区间加上值直接转换成把入栈节点和出栈节点之间的数加上一个值(区间修改?)

然后就Splay了


我是因为听闻非旋Treap常数大才没有写,没想到Splay也卡常啊。。。


这代码过不了啊

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define LL long long
#define pi pair<int,int>
inline int read(){
int ans=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')w=-1,c=getchar();
while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
return ans*w;
}
inline void print(LL x){
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar((x-(x/10)*10)+'0');
}
struct Edge{int v,next;}E[N];
int head[N]={0},tot=0;
int n,q,id[N],dfn=0;
int w[N];
pi st[N];
inline void add(int u,int v){
E[++tot]=(Edge){v,head[u]};
head[u]=tot;
}
inline void dfs(int u,int fa){
id[++dfn]=u;
st[dfn]=(pi){w[u],1};
for(int i=head[u];i;i=E[i].next)
if(E[i].v!=fa)dfs(E[i].v,u);
id[++dfn]=u+n;
st[dfn]=(pi){-w[u],-1};
}
int root,fa[N],son[N][2],cnt=0;
int tag[N],siz[N],num[N],typ[N];
LL sum[N],val[N];
inline void pushup(int t){
sum[t]=sum[son[t][0]]+sum[son[t][1]]+val[t];
siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;
num[t]=num[son[t][0]]+num[son[t][1]]+typ[t];
}
inline void pushnow(int t,LL vl){
tag[t]+=vl;
if(typ[t]>0)val[t]+=vl;
else val[t]-=vl;
sum[t]+=vl*num[t];
}
inline void pushdown(int t){
if(fa[t])pushdown(fa[t]);
if(tag[t]){
pushnow(son[t][0],tag[t]);
pushnow(son[t][1],tag[t]);
tag[t]=0;
}
}
inline bool Son(int t){return son[fa[t]][1]==t;}
inline void rotate(int t){
int f=fa[t],g=fa[f];
bool a=Son(t),b=a^1;
if(g)son[g][Son(f)]=t;fa[t]=g;
son[f][a]=son[t][b];fa[son[f][a]]=f;
son[t][b]=f;fa[f]=t;
pushup(f);pushup(t);
}
inline void splay(int t,int tp){
if(!t)return;
pushdown(t);
while(fa[t]!=tp){
int f=fa[t];
if(fa[f]!=tp){
if(Son(t)^Son(f))rotate(t);
else rotate(f);
}
rotate(t);
}
if(!tp)root=t;
}
inline int build(int l,int r){
if(l>r)return 0;
int mid=(l+r)>>1,t=id[mid];
val[t]=sum[t]=st[mid].first;
num[t]=typ[t]=st[mid].second;
siz[t]=1;tag[t]=0;
if(l==r)return t;
fa[son[t][0]=build(l,mid-1)]=t;
fa[son[t][1]=build(mid+1,r)]=t;
pushup(t);
return t;
}
inline int pre(int pos){
int t=son[pos][0];
while(son[t][1])t=son[t][1];
return t;
}
inline int nxt(int pos){
int t=son[pos][1];
while(son[t][0])t=son[t][0];
return t;
}
inline void modify(int l,int r,LL vl){
int ll=pre(l),rr=nxt(r);
splay(ll,0);
splay(rr,root);
pushnow(son[son[root][1]][0],vl);
}
inline LL query(int pos){
splay(pos,0);
return sum[son[pos][0]]+val[pos];
}
inline void change(int pos,int father){
int lx=pre(pos),rx=nxt(pos+n);
splay(lx,0);
splay(rx,lx);
int t=son[rx][0];
fa[t]=0;son[rx][0]=0;
int lf=nxt(father);
splay(father,0);
splay(lf,father);
son[lf][0]=t;fa[t]=lf;
pushup(lf);
pushup(father);
}
int main(){
n=read();
for(int i=2;i<=n;i++){
int x=read();
add(i,x);add(x,i);
}
for(int i=1;i<=n;i++)w[i]=read();
dfs(1,0);
id[0]=n*2+1;st[0]=(pi){0,1};
id[dfn+1]=n*2+2;st[dfn+1]=(pi){0,-1};
root=build(0,dfn+1);
int m=read();
while(m--){
char c[5];
scanf("%s",c);
if(c[0]=='Q'){
int x=read();
print(query(x));
printf("\n");
}else if(c[0]=='C'){
int x=read(),y=read();
change(x,y);
}else{
int x=read(),y=read();
modify(x,x+n,y);
}
}
return 0;
}

BZOJ3786 星系探索 【Splay维护dfs序】*的更多相关文章

  1. bzoj3786星系探索(splay维护dfs序)

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

  2. 【BZOJ 3729】3729: Gty的游戏 (Splay维护dfs序+博弈)

    未经博主同意不得转载 3729: Gty的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 448  Solved: 150 Description ...

  3. BZOJ3786: 星系探索 Splay+DFS序

    题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...

  4. bzoj3786星系探索 splay

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

  5. BZOJ 3729 splay维护DFS序+博弈论

    思路: 这像是 阶梯Nim之类的东西 我们 直接把sg函数 设成mod(L+1)的 一棵子树 向下的奇数层上的石子xor起来 就是答案 有加点和改值的操作 就splay维护一下 //By Sirius ...

  6. BZOJ3786:星系探索(Splay,括号序)

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

  7. BZOJ 3786 星系探索 (splay+dfs序)

    题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...

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

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

  9. BZOJ 3786 星系探索 ——Splay

    子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...

随机推荐

  1. 从U盘安装linux(前人踩坑后人乘凉)

    今天踩了一个大坑,网上的教程从u盘安装linux少了一个关键步骤导致我挣扎了两个小时 废话不多说,开始需要准备一些东西 1.从官网下载一个Ubuntu 10.04的镜像 2.一个大于等于1G的支持启动 ...

  2. Javascript知识点汇总-初级篇

    JavaScript的数据类型都有什么? 基本数据类型:String,Boolean,Number,Undefined, Null 引用数据类型:Object(Array,Date,RegExp,Fu ...

  3. 24,25-request对象

    var http = require('http'); var server = http.createServer(); server.listen() console.log(server.add ...

  4. vim与shell切换

    扩展一些vim的知识. vim与shell切换 :shell 可以在不关闭vi的情况下切换到shell命令行. :exit 从shell回到vim. 文件浏览 :Ex 开启目录浏览器,可以浏览当前目录 ...

  5. Android数据库框架-----ORMLite 的基本用法

    ORMLite 是一款非要流行的Android平台上的数据库框架,性能优秀,代码简洁: 简述: 优点: 1.轻量级:2.使用简单,易上手:3.封装完善:4.文档全面. 缺点:1.基于反射,效率较低(本 ...

  6. C++(二十八) — 构造函数的初始化列表

    1.解决的问题: 在 B 类中,组合了一个 A 类对象,其中A类设计了构造函数.由于构造函数的调用规则,设计了构造函数就必须调用,但在定义B类时没有机会初始化A,因此采用构造函数的初始化列表来解决. ...

  7. 12.详解Condition的await和signal等待通知机制

    1.Condition简介 任何一个java对象都天然继承于Object类,在线程间实现通信的往往会应用到Object的几个方法,比如wait(),wait(long timeout),wait(lo ...

  8. Neutron三层网络服务实现原理

    Neutron 对虚拟三层网络的实现是通过其 L3 Agent (neutron-l3-agent).该 Agent 利用 Linux IP 栈.route 和 iptables 来实现内网内不同网络 ...

  9. Ti IPNC Web网页之ActiveX控件

    Ti IPNC Web网页之ActiveX控件 本篇介绍关于TI IPNC网页中播放器相关的东西. gStudio工程中添加播放器并控制播放器 打开IPNC网页时首先会自动下载ActiveX控件并安装 ...

  10. 报错:java.lang.IllegalArgumentException: object is not an instance of declaring class

    反射的报错信息如下: java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.r ...