BZOJ3786 星系探索 【Splay维护dfs序】*
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<di,xi<=n,wi,qi<=100000" role="presentation">1<di,xi<=n,wi,qi<=1000001<di,xi<=n,wi,qi<=100000.保证操作合法。注意wi>=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序】*的更多相关文章
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- 【BZOJ 3729】3729: Gty的游戏 (Splay维护dfs序+博弈)
未经博主同意不得转载 3729: Gty的游戏 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 448 Solved: 150 Description ...
- BZOJ3786: 星系探索 Splay+DFS序
题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...
- bzoj3786星系探索 splay
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1314 Solved: 425[Submit][Status][Discuss ...
- BZOJ 3729 splay维护DFS序+博弈论
思路: 这像是 阶梯Nim之类的东西 我们 直接把sg函数 设成mod(L+1)的 一棵子树 向下的奇数层上的石子xor起来 就是答案 有加点和改值的操作 就splay维护一下 //By Sirius ...
- BZOJ3786:星系探索(Splay,括号序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...
- [BZOJ3786]星系探索(伪ETT)
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1638 Solved: 506[Submit][Status][Discuss ...
- BZOJ 3786 星系探索 ——Splay
子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...
随机推荐
- vcf2maf
1.https://github.com/mskcc/vcf2maf 2.https://github.com/cbare/vcf2maf
- Tomcat 环境搭建
最近在工作之余,看到了一些 Tomcat 的基础资料,感觉蛮好.同时也回忆起自己刚毕业要参加工作那会对 Tomcat 也是各种资料各种查,实属不易.为此,针对最近整理的一些基础,把 Tomcat 基本 ...
- setTimout执行时间
在浏览器中,JavaScript引擎是单线程执行的.也就是说,在同一时间内,只能有一段代码被JavaScript引擎执行.页面加载时,JavaScript引擎会顺序执行页面上所有JavaScript代 ...
- 由angular命令行工具(angular-cli)生成的目录和文件
e2e目录:是端到端的测试目录,包含基本的测试桩.是用来做自动测试的. src:应用源代码目录.我们写的所有代码都应该在这里面. app:包括应用的组件和模块.我们自己写的绝大部分代码都是写在这个目录 ...
- Floyd判圈算法 Floyd Cycle Detection Algorithm
2018-01-13 20:55:56 Floyd判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm) ...
- IdentityServer4在Asp.Net Core中的应用(三)
今天的内容是授权模式中的简化模式,还是先看以下授权流程图: 在这种模式中我们将与OpenID结合使用,所以首先我们要了解OpenID和OAuth的区别,关于他们的区别,在我上一篇博客<理解Ope ...
- Oracle Procedure记录
1.定义 所谓存储过程(Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过 编译后存储在数据库系统中.在使用时候,用户通过指定已经定义的存储过程名字并给出相应的存储 ...
- Python读取指定文件夹(包括当前目录、子目录、子文件)
http://blog.csdn.net/lsq2902101015/article/details/51305825
- Python之匿名函数(filter,map,reduce)
参考博客:Python匿名函数详解--http://blog.csdn.net/csdnstudent/article/details/40112803 Python内建函数之——filter,map ...
- 控制台小游戏-贪吃蛇,c++和c#版
说是c++版,其实只是用到了c++的cout和cin而已.这是我做的第二个控制台游戏,基本上每一行代码都加上了注释. 游戏嘛,我觉得重要的是了解他的思想,所以后期学了面向对象之后这个游戏的代码我也没有 ...