BZOJ_3786_星系探索_splay维护出栈入栈序
BZOJ_3786_星系探索_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
考虑用splay维护出栈入栈序,这样我们求前缀和就是点到根路径的权值和了。
换根操作也比较容易实现,因为子树对应着一段区间,直接移动子树即可。
就是子树加不太好做,因为是加点权,不包含系数。
于是我们再维护出有多少个正数有多少个负数即可。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 200050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int head[N],to[N],nxt[N],cnt,ch[N][2],f[N],rt,n,m,tot,dfn[N],siz[N],son[N];
int zc[N],fc[N],a[N],type[N],val[N],w[N],fa[N];
ll sum[N];
int del[N];
char pbuf[100000],*pp=pbuf;
__attribute__((optimize("-O3")))void push(const char ch) {
if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
*pp++=ch;
}
__attribute__((optimize("-O3")))void write(ll x) {
static int sta[50];
int top=0;
do{sta[++top]=x%10,x/=10;}while(x);
while(top) push(sta[top--]+'0');
push('\n');
}
__attribute__((optimize("-O3")))inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
__attribute__((optimize("-O3")))int rd() {
int x=0; char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
__attribute__((optimize("-O3")))char rc() {
char s=nc();
while(s!='Q'&&s!='C'&&s!='F') s=nc();
return s;
}
__attribute__((optimize("-O3")))void give(int p,int v) {
val[p]+=v; del[p]+=v; sum[p]+=1ll*(zc[p]-fc[p])*v;
}
__attribute__((optimize("-O3")))void pushup(int p) {
if(!p) return ;
siz[p]=1;
zc[p]=fc[p]=0;
if(type[p]==1) zc[p]=1;
else if(type[p]==-1) fc[p]=1;
sum[p]=val[p]*type[p];
siz[p]+=siz[ls],sum[p]+=sum[ls],zc[p]+=zc[ls],fc[p]+=fc[ls];
siz[p]+=siz[rs],sum[p]+=sum[rs],zc[p]+=zc[rs],fc[p]+=fc[rs];
}
__attribute__((optimize("-O3")))void pushdown(int p) {
if(del[p]) {
if(ls) give(ls,del[p]);
if(rs) give(rs,del[p]);
del[p]=0;
}
}
__attribute__((optimize("-O3")))void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
if(rt==y) rt=x;
pushup(y); pushup(x);
}
__attribute__((optimize("-O3")))void update(int p,int y) {
if(f[p]!=y) update(f[p],y);
pushdown(p);
}
__attribute__((optimize("-O3")))void splay(int x,int y) {
update(x,y);
for(int d;(d=f[x])!=y;rotate(x))
if(f[d]!=y)
rotate(get(x)==get(d)?d:x);
}
__attribute__((optimize("-O3")))inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
__attribute__((optimize("-O3")))void dfs(int x) {
int i;a[++tot]=x; type[tot+1]=1; dfn[x]=tot+1; val[tot+1]=w[x];
for(i=head[x];i;i=nxt[i]) {
f[to[i]]=x;
dfs(to[i]);
}
a[++tot]=x; type[tot+1]=-1; son[x]=tot+1; val[tot+1]=w[x];
}
__attribute__((optimize("-O3")))void build(int fa,int l,int r) {
if(l>r) return ;
int mid=(l+r)>>1;
f[mid]=fa;
ch[fa][mid>fa]=mid;
build(mid,l,mid-1);
build(mid,mid+1,r);
pushup(mid);
}
__attribute__((optimize("-O3")))int pre() {
int p=ch[rt][0];
for(;rs;p=rs) pushdown(p);
return p;
}
__attribute__((optimize("-O3")))int suc() {
int p=ch[rt][1];
for(;ls;p=ls) pushdown(p);
return p;
}
__attribute__((optimize("-O3")))void huan(int x,int y) {
splay(dfn[x],0); int p2=pre();
splay(son[x],0); int p4=suc();
splay(p2,0); splay(p4,p2);
int p5=ch[p4][0]; f[p5]=0; ch[p4][0]=0;
pushup(p4); pushup(p2);
int p6=dfn[y];
splay(p6,0); int p7=suc();
splay(p7,p6);
ch[p7][0]=p5; f[p5]=p7;
pushup(p5); pushup(p7); pushup(p6);
}
__attribute__((optimize("-O3")))int find(int x) {
int p=rt;
while(1) {
pushdown(p);
if(x<=siz[ls]) p=ls;
else {
x-=siz[ls]+1;
if(!x) return p;
p=rs;
}
}
}
__attribute__((optimize("-O3")))void print() {
int i,p;
for(i=1;i<=tot+2;i++) {
p=find(i);
printf("i=%d,p=%d,val[p]=%d,f[p]=%d,zc[p]=%d,fc[p]=%d\n",i,p,val[p],f[p],zc[p],fc[p]);
}
}
__attribute__((optimize("-O3")))int main() {
n=rd();
register int i,x,y,p;
for(i=2;i<=n;i++) {
x=rd();
add(x,i);
}
for(i=1;i<=n;i++) w[i]=rd();
dfs(1);
build(0,1,tot+2);
rt=(tot+3)>>1;
m=rd();
char opt;
while(m--) {
opt=rc(); x=rd();
if(opt=='Q') {
x=dfn[x];
// splay(x,0); p=suc();
// splay(1,0); splay(p,1);
splay(1,0);
splay(x,1);
for(p=ch[x][1];ls;p=ls);
splay(p,1);
write(sum[ls]);
}else if(opt=='C') {
y=rd();
// scanf("%d",&y);
if(fa[x]!=y) huan(x,y),fa[x]=y;
}else {
y=rd();
// scanf("%d",&y);
int q=dfn[x];
splay(q,0); p=pre();
int t1=p;
q=son[x];
splay(q,0); p=suc();
splay(t1,0); splay(p,t1);
give(ls,y);
}
}
fwrite(pbuf,1,pp-pbuf,stdout);
}
BZOJ_3786_星系探索_splay维护出栈入栈序的更多相关文章
- BZOJ_2819_Nim_树状数组维护出栈入栈序
BZOJ_2819_Nim_树状数组维护出栈入栈序 Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任 ...
- BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...
- BZOJ3772精神污染——可持久化线段树+出栈入栈序
题目描述 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户 ...
- 出栈入栈动画demo
项目做了一个切换界面动画的功能,用到了出栈入栈的,写了一个demo package com.myron.stackview; import java.util.Stack; import androi ...
- BZOJ_2434_[Noi2011]阿狸的打字机_AC自动机+出栈入栈序+树状数组
BZOJ_2434_[Noi2011]阿狸的打字机_AC自动机+出栈入栈序+树状数组 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印 ...
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- C++中栈的出栈,入栈规则:A,B,C,D,E
考题: 栈底至栈顶一次存放元素 ABCD 在第五个元素E入栈之前 栈中元素可以出栈,则出栈序列可能是_____a d___________. a. ABCED b. DBCEA c. CD ...
- [置顶] 栈/入栈/出栈顺序(c语言)-linux
说明: 1.栈底为高地址,栈顶为低地址. 2.入栈顺序:从右到左. 解释1:栈在内存中的结构 [注:0x00 到 0x04之间间隔4个地址] 入栈:指针先指向0x10,从高地址向低地址方向填数值,最终 ...
- 剑指 Offer 31. 栈的压入、弹出序列 + 入栈顺序和出栈顺序的匹配问题
剑指 Offer 31. 栈的压入.弹出序列 Offer_31 题目详情: 解析: 这里需要使用一个栈来模仿入栈操作. package com.walegarrett.offer; /** * @Au ...
随机推荐
- linux删除空行操作:awk、grep、tr、sed
如下:如何删除空行 shen\nshen\\n sen seh sehe she she 真正删除空行,可以使用vim: 通过命令模式删除空行.vim在命令模式下(在vim里输入英文字符:进入命令模式 ...
- 全面解读java虚拟机(面试考点大全)d
学习java以来,jvm的原理已经看过好多遍了,可是很多知识点都串不起来. 今天我把jvm相关知识整理了一下,看完之后肯定会对JVM很的清楚. JVM是虚拟机,也是一种规范,他遵循着冯·诺依曼体系结构 ...
- svn hooks 实现自动更新
搞来搞去,原来是hooks 下面的脚本名称必须是post-commit才可以, 写成fly-commit一直不行.晕死~~~ https://serverfault.com/questions/144 ...
- java内存模型(Java Memory Model)
内容导航: Java内存模型 硬件存储体系结构 Java内存模型和硬件存储体系之间的桥梁: 共享对象的可见性 竞争条件 Java内存模型规定了JVM怎样与计算机存储系统(RAM)协调工作.JVM是一个 ...
- 直接返回list不封装的结果集
直接返回list不封装的结果集,在Jsp访问方式: 1.封装成map访问 2.用jstl: <c:forEach var="images" items="${lis ...
- openssl之BIO系列之12---文件描写叙述符(fd)类型BIO
文件描写叙述符(fd)类型BIO ---依据openssl doc\crypto\bio_s_fd.pod翻译和自己的理解写成 (作者:DragonKing Mailwzhah@263.net 公布于 ...
- 每天进步一点点——Linux中的线程局部存储(二)
转载请说明出处:http://blog.csdn.net/cywosp/article/details/26876231 在Linux中另一种更为高效的线程局部存储方法,就是使用keyword ...
- LNMPA遇到504 Gateway time-out错误的解决方法
Nginx的特点是处理静态很给力,Apache的特点是处理动态很稳定,两者结合起来便是LNMPA,nginx处理前端,apache处理后端,这样处理静态会很快,处理动态会很稳定. 当我以为安装完成以后 ...
- substr使用注意
substr使用时要判断起点和长度是否超过了串本身的长度,否则会抛异常
- LeetCode -- 反转英文单词
问题:给定英文句子.反转里面的每一个单词.比如"the sky is blue" 反转后为 "blue is the sky" 实现思路:对英文句子每一个字符做 ...