题目链接:\(BZOJ\)

本题通过 \(dyf\_DYF\) 的题解理解 \(ETT\),代码则借鉴 \(lcyfrog\) 的题解,图片则使用了何太狼的题解。在此笔者感谢这三位神犇。


声明变量:

\(ls\):左儿子

\(rs\):右儿子

\(sz\):子树大小

\(rk\):对应堆值

\(fa\):节点父亲

\(sm\):子树权值和

\(p\):\(1/-1\) 表示 第一个欧拉序/第二个欧拉序,下面会讲

\(w\):该节点自身权值

\(tp\):子树 \(p\) 之和

\(tg\):懒标记


零、题目大意

给你一颗有根树,需要完成以下三个操作:

  • 计算一个点到根节点路径上的权值和
  • 将一颗子树权值全部增加一个定值
  • 将一颗子树接到另一个节点下面

一、前置知识:欧拉序

欧拉序有两种,我们分开来讲:

(1)第一类欧拉序

考虑用 \(dfs\) 的走法走满整棵树,每到一个节点欧拉序末尾加一个数。

不过,与 \(dfs\) 序不同的是,每遍历完一棵子树后,就得再加一次。

心动不如画图,我们可以通过这张图来理解:



根据图中走法,很容易得出欧拉序为:\(1,2,4,7,4,8,4,9,4,2,5,2,1,3,6,3,1\),可以发现,有 \(2n-1\) 个节点。

这种欧拉序可以快速求出两点最近公共祖先,但与此题无关,关键在第二个。

(2)第二类欧拉序

与上一类不同的是,本类欧拉序是在进入和离开时在末尾增加。

再来一张图:



欧拉序为:\(1,2,4,7,7,8,8,9,9,4,5,5,2,3,6,6,3,1\),有 \(2n\) 个节点。


二、初步思考

我们发现本题要求从一个点到根的路径上的权值和,还有子树加,于是考虑可爱的欧拉序。

发现假如将第二类欧拉序中,离开时增加的节点们全部标记为负,欧拉序维护权值,那么从 \(x\) 到根节点的权值和即为从第一个节点到 \(x\) 第一次出现的位置的和。

这下,我们就可以把树上问题转化为序列问题了。

在这里,我们再声明两个变量,以方便叙述:

\(dfn\):第一次出现位置

\(low\):第二次出现位置

那么对 \(x\) 子树加上 \(y\) 就可以变成在 \(dfn[x]+y\),在 \(low[x]-y\)。


三、加入平衡树

考虑将一个子树接在另一个点上的操作。

发现在移动 \(x\) 的子树接到 \(y\) 下时,只是将 \([dfn[x],low[x]]\) 移动到了 \(dfn[y]\) 后(大家可以自行模拟)。

移动区间位置,单点修改,区间查询,不是线段树,只能是平衡树了。

支持区间操作的平衡树,有 \(fhq\ treap\) 和 \(splay\) 两种,前者似乎更方便一些,因此笔者用了 \(fhq\ treap\)。

当然,如果你对 \(splay\) 有着深厚的情感,你也可以看 \(dyf\_DYF\) 对于 \(splay\) 方法的讲解


四、标程

#include<bits/stdc++.h>
#define ll long long
#define ls(x) pl[x].ls
#define rs(x) pl[x].rs
#define sz(x) pl[x].sz
#define rk(x) pl[x].rk
#define fa(x) pl[x].fa
#define sm(x) pl[x].sm
#define p(x) pl[x].p
#define w(x) pl[x].w
#define tp(x) pl[x].tp
#define tg(x) pl[x].tg
#define N 300005
using namespace std;
struct fhq{
int ls,rs,sz,rk,fa;
ll sm,p,w,tp,tg;
}pl[N];int fhq_fail,dfn[N],low[N],f;
int make_node(int x,int y){
int a=++fhq_fail;
sz(a)=1;w(a)=sm(a)=x*y;
rk(a)=rand();p(a)=tp(a)=y;
return a;
}struct fhq_treap{
int rt;fhq_treap(){rt=0;}
void pushup(int pp){
sz(pp)=sz(ls(pp))+sz(rs(pp))+1;
tp(pp)=tp(ls(pp))+tp(rs(pp))+p(pp);
sm(pp)=sm(ls(pp))+sm(rs(pp))+w(pp);
if(ls(pp)) fa(ls(pp))=pp;
if(rs(pp)) fa(rs(pp))=pp;
}void tag(int q,ll pp){
w(q)+=p(q)*pp;
sm(q)+=tp(q)*pp;
tg(q)+=pp;
}void pushdown(int pp){
if(!tg(pp)) return;
tag(ls(pp),tg(pp));
tag(rs(pp),tg(pp));
tg(pp)=0;
}void spilt(int pp,int a,int &x,int &y){
if(!pp){x=y=0;return;}pushdown(pp);
if(a>sz(ls(pp))) x=pp,spilt(rs(pp),a-sz(ls(pp))-1,rs(x),y);
else y=pp,spilt(ls(pp),a,x,ls(y));pushup(pp);
}int merge(int x,int y){
pushdown(x);pushdown(y);
if(!x||!y) return x+y;
if(rk(x)<rk(y)){
rs(x)=merge(rs(x),y);
pushup(x);return x;
}ls(y)=merge(x,ls(y));
pushup(y);return y;
}int rank(int x){
int re=sz(ls(x))+1;
while(fa(x)){
if(rs(fa(x))==x)
re+=sz(ls(fa(x)))+1;x=fa(x);
}return re;
}void add(int a,ll b){
int x,y,z;
f=1;spilt(rt,rank(dfn[a])-1,x,z);fa(x)=fa(z)=0;f=0;
spilt(z,rank(low[a]),y,z);fa(y)=fa(z)=0;
tag(y,b);rt=merge(merge(x,y),z);fa(rt)=0;
}void work(int a,int b){
int x,y,z;
spilt(rt,rank(dfn[a])-1,x,z);fa(x)=fa(z)=0;
spilt(z,rank(low[a]),y,z);fa(y)=fa(z)=0;
rt=merge(x,z);fa(rt)=0;spilt(rt,rank(dfn[b]),x,z);
rt=merge(merge(x,y),z);fa(rt)=0;
}
}tr;int n,t,b[N];vector<int>g[N];
void dfs(int x){
dfn[x]=make_node(b[x],1);tr.rt=tr.merge(tr.rt,dfn[x]);
for(int i=g[x].size()-1;i>=0;i--) dfs(g[x][i]);
low[x]=make_node(b[x],-1);tr.rt=tr.merge(tr.rt,low[x]);
}signed main(){
srand(20040523);cin>>n;
for(int i=2;i<=n;i++){
int x;cin>>x;
g[x].push_back(i);
}for(int i=1;i<=n;i++) cin>>b[i];
dfs(1);cin>>t;while(t--){
char c;int d;ll e;cin>>c;
if(c=='Q'){
int x,y;cin>>d;
tr.spilt(tr.rt,tr.rank(dfn[d]),x,y);
cout<<sm(x)<<"\n";tr.merge(x,y);
}if(c=='C') cin>>d>>e,tr.work(d,e);
if(c=='F') cin>>d>>e,tr.add(d,e);
}return 0;
}//Kaká

[BZOJ3786] 星系探索 题解的更多相关文章

  1. [BZOJ3786]星系探索

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

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

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

  3. bzoj3786星系探索 splay

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

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

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

  5. [BZOJ3786] 星系探索(括号序列+Splay)

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

  6. BZOJ3786星系探索——非旋转treap(平衡树动态维护dfs序)

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

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

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

  8. BZOJ3786: 星系探索(伪ETT)

    题面 传送门 题解 坑啊--我好像把\(Splay\)的东西全忘光了-- \(ETT\)(\(Euler\ Tour\ Tree\))是一种可以资瓷比\(LCT\)更多功能的数据结构,然而不管是功能还 ...

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

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

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

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

随机推荐

  1. groovy 内存回收测试

    问题 在使用我们的开发平台时,客户怀疑我们的动态执行脚本会导致系统内存回收的问题,导致系统不响应,为此我专门针对这个问题,做一下详细的测试,看看是不是到底有什么影响. 测试步骤 1.使用编写一个控制器 ...

  2. 从Delphi到Lazarus——Lazarus开发环境使用入门教程

    0.前言 曾经有过更换开发环境体验的编程爱好者都会有同样的感受:打开新更换的开发环境后,看到陌生的界面无从下手.想写一段小程序试一试,却你找不到自己需要的组件在哪里. 其实,我们每到一个新地方,首先要 ...

  3. OS之《死锁》

    什么是死锁 一组进程中的每一个进程都在等待仅由该组进程中其他进程才能引发的事件,这样就形成死锁了. 死锁的原因 竞争不可抢占的资源 竞争可消耗资源 进程推进顺序不当 死锁产生的必要条件 1.互斥条件: ...

  4. Linux(ubuntu18)下 Qt linguist 在哪里 找不到

    1.首先找到Qt安装目录. 2.通过命令查找linguist. find . -name linguist 3.制作桌面快捷方式. 在/usr/share/applications目录下新建lingu ...

  5. 如何将java私有库(jar)提交至公服/公共仓库(central repository)-手动版

    如何将java私有库(jar)提交至公服/公共仓库(central repository)-手动版 准备 GunPG(用于asc签名) 项目代码(建议是maven结构的) sonatype账号(htt ...

  6. 【Amadeus原创】查看正在运行的docker run参数

    如何查看一个运行docker 容器的docker run启动参数,假设没有使用docker-compose这样的编排工具. 现在我如何进行重启,如何找回此前的启动命令? [root@mysql3 ~] ...

  7. GraphQL Part II: 中间件

    GraphQL Part II: 中间件 如果您熟悉 ASP.NET Core 的中间件,您可能注意到在我们上一篇博客中我们已经拥有了一个中间件.在初始的空白应用中,中间件的职责是返回 hello W ...

  8. Qt/C++音视频开发65-切换声卡/选择音频输出设备/播放到不同的声音设备/声卡下拉框

    一.前言 近期收到一个用户需求,要求音视频组件能够切换声卡,首先要在vlc上实现,于是马不停蹄的研究起来,马上查阅对应vlc有没有自带的api接口,查看接口前,先打开vlc播放器,看下能不能切换,因为 ...

  9. ERROR: SSL peer shut down incorrectly错误解决(Android Studio)

    错误信息:ERROR: SSL peer shut down incorrectly错误解决(Android Studio) 错误原因:android studio在下载"gradle-4. ...

  10. 零基础Windows Server搭建部署Word Press 博客系列教程(3):弱鸡变猛男之部署CDN加速和缓存加速

    我们博客里面存在的各种媒体文件.压缩文件.脚本文件,这些文件可能很大而且不需要随时生成.如果我们的服务器带宽很小,访问我们网站的用户等待加载完成就需要很长时间,那么访问速度会很慢.因此我们需要通过第三 ...