数据结构&图论:欧拉游览树
ETT可以称为欧拉游览树,它是一种和欧拉序有关的动态树(LCT是解决动态树问题的一种方案,这是另一种)
dfs序和欧拉序是把树问题转化到区间问题上然后再用数据结构去维护的利器
通过借助这两种形式能够完成子树的查询和修改,这是LCT所不能胜任的工作
所谓的ETT就是通过动态维护欧拉序来实现动态树
它能完成换父亲(Cut和Link操作)
修改子树(LCT实现不了)
查询结点到根的信息
当然它对比于LCT还是有局限性的
这些操作通过DFS序+Splay也可以完成
只不过我们通俗地把欧拉序+Splay称作ETT而已
这个代码在我交上去的时候WA了一发,printf函数在处理long long的时候一定要小心
代码细节等以后对DFS序和欧拉序了解更加充分以及对数据结构掌握的更好的时候再回过头来看
#include<cstdio>
using namespace std;
const int maxn=;
const int maxm=;
int n,cnt,tot,m;
int a[maxn],g[maxn];
int lch[maxn],rch[maxn],dfn[maxn];
int fa[maxn],size[maxn],mark[maxn];
long long lazy[maxn],sum[maxn],val[maxn];
int ch[maxn][];
struct Edge
{
int t,next;
}e[maxm];
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void addedge(int u,int v)
{
cnt++;
e[cnt].t=v;e[cnt].next=g[u];
g[u]=cnt;
}
void dfs(int x) //计算欧拉序
{
lch[x]=++tot;
dfn[lch[x]]=x;
for(int tmp=g[x];tmp;tmp=e[tmp].next)
dfs(e[tmp].t);
rch[x]=++tot;
dfn[rch[x]]=-x;
}
void push_down(int x)
{
if(x&&fa[x]) push_down(fa[x]);
if(x==||lazy[x]==) return;
lazy[ch[x][]]+=lazy[x];
lazy[ch[x][]]+=lazy[x];
val[ch[x][]]+=lazy[x]*mark[ch[x][]];
val[ch[x][]]+=lazy[x]*mark[ch[x][]];
sum[ch[x][]]+=(long long)size[ch[x][]]*lazy[x];
sum[ch[x][]]+=(long long)size[ch[x][]]*lazy[x];
lazy[x]=;
}
int dir(int x)
{
return ch[fa[x]][]==x;
}
void push_up(int x)
{
sum[x]=sum[ch[x][]]+sum[ch[x][]]+val[x];
size[x]=size[ch[x][]]+size[ch[x][]]+mark[x];
}
void rotate(int x,int d)
{
int tmp=ch[x][d^];
ch[x][d^]=ch[tmp][d];
if(ch[x][d^]) fa[ch[x][d^]]=x;
fa[tmp]=fa[x];
if(fa[x]) ch[fa[x]][dir(x)]=tmp;
fa[x]=tmp;
ch[tmp][d]=x;
push_up(x);push_up(tmp);
}
void splay(int x,int goal)
{
push_down(x);
while(fa[x]!=goal)
{
if(fa[fa[x]]!=goal&&dir(x)==dir(fa[x]))
rotate(fa[fa[x]],dir(x)^);
rotate(fa[x],dir(x)^);
}
}
int find_left(int x)
{
splay(x,);
x=ch[x][];
while(ch[x][]) x=ch[x][];
return x;
}
int find_right(int x)
{
splay(x,);
x=ch[x][];
while(ch[x][]) x=ch[x][];
return x;
}
int build(int l,int r)
{
if(l>r) return ;
int mid=(l+r)>>;
if(mid<r)
{
ch[mid][]=build(mid+,r);
fa[ch[mid][]]=mid;
}
if(l<mid)
{
ch[mid][]=build(l,mid-);
fa[ch[mid][]]=mid;
}
if(dfn[mid]>) val[mid]=a[dfn[mid]];
else val[mid]=-a[-dfn[mid]]; if(dfn[mid]>) mark[mid]=;
else mark[mid]=-; push_up(mid);
return mid;
}
int main()
{
int x,y;
char opt;
n=read();
for(int i=;i<=n;i++)
{
x=read();
addedge(x,i);
}
dfs();
for(int i=;i<=n;i++) a[i]=read();
build(,tot+);
m=read();
while(m--)
{
opt=getchar();
while(opt!='Q'&&opt!='C'&&opt!='F') opt=getchar();
x=read();
if(opt=='Q')
{
splay(lch[x],);
printf("%lld\n",sum[ch[lch[x]][]]+val[lch[x]]);
}
else if(opt=='C')
{
y=read();
int aa=find_left(lch[x]),bb=find_right(rch[x]);
splay(aa,);splay(bb,aa);
int tmp=ch[bb][];
ch[bb][]=;
push_up(bb);push_up(aa);
x=find_left(rch[y]);
splay(x,);splay(rch[y],x);
fa[tmp]=rch[y];
ch[rch[y]][]=tmp;
push_up(rch[y]);push_up(x);
}
else
{
y=read();
int aa=find_left(lch[x]),bb=find_right(rch[x]);
splay(aa,);splay(bb,aa);
lazy[ch[bb][]]+=y;
val[ch[bb][]]+=y*mark[ch[bb][]];
sum[ch[bb][]]+=(long long)size[ch[bb][]]*y;
}
}
return ;
}
数据结构&图论:欧拉游览树的更多相关文章
- BZOJ 3786: 星系探索 欧拉游览树
一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序 #include <cstring> #include <algorithm> ...
- 三维CAD塑造——基于所述基本数据结构一半欧拉操作模型
三维CAD塑造--基于所述基本数据结构一半欧拉操作模型(elar, B_REP) (欧拉操作 三维CAD建模课程 三维CAD塑造 高曙明老师 渲染框架 brep 带洞 带柄 B_REP brep ...
- HYSBZ - 3813 奇数国 欧拉函数+树状数组(线段树)
HYSBZ - 3813奇数国 中文题,巨苟题,巨无敌苟!!首先是关于不相冲数,也就是互质数的处理,欧拉函数是可以求出互质数,但是这里的product非常大,最小都2100000,这是不可能实现的.所 ...
- POJ2513 欧拉 + 字典树
POJ 2513 有N根木棒,一根木棒有2头,我们把每头涂色(相同或不同),如果2根木棒有相同颜色的一端就可以连接,颜色全部不同就不能连接,现在给你N根木棒以及它们的颜色,问最后能不能链接成1条链. ...
- [BZOJ3772]精神污染 主席树上树+欧拉序
3772: 精神污染 Time Limit: 10 Sec Memory Limit: 64 MB Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位 ...
- BZOJ 4034 树上操作(树的欧拉序列+线段树)
刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- 树的遍历顺序 - dfs序|欧拉序|dfn序(备忘)
(仅作备忘) dfs序是dfs过程中对于某节点进入这个节点的子树和离开子树的顺序 满足每个节点都会在dfs序上出现恰好两次 任意子树的dfs序都是连续的 欧拉序是dfs过程中经过节点的顺序 每个节点至 ...
- LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树
分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...
- HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树
lca的做法还是非常明显的.简单粗暴, 只是不是正解.假设树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的.预计就是放在splay上剖分一 ...
随机推荐
- codeforces 228E The Road to Berland is Paved With Good Intentions(2-SAT)
Berland has n cities, some of them are connected by bidirectional roads. For each road we know wheth ...
- 面试中要注意的 3 个 JavaScript 问题
JavaScript 是 所有现代浏览器 的官方语言.因此,各种语言的开发者面试中都会遇到 JavaScript 问题. 本文不讲最新的 JavaScript 库,通用开发实践,或任何新的 ES6 函 ...
- Java学习个人备忘录之面向对象概念
对象,其实就是该类事物实实在在存在的个体. 类与对象之间的关系?类:一类事物的描述.对象:该类事物的实例.在java中通过new来创建的.举例来说,类就是汽车说明书,类只能在理论上造一辆汽车,并且这个 ...
- 软工实践Alpha冲刺(2/10)
队名:我头发呢队 组长博客 作业博客 杰(组长) 过去两天完成了哪些任务 查看了讯飞开放平台的sdk 查阅了Google Material Design 2的官方文档 接下来的计划 继续打磨UI界面: ...
- lintcode-196-寻找缺失的数
196-寻找缺失的数 给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数. 样例 N = 4 且序列为 [0, 1, 3] 时,缺失的数为2. 挑战 在数组上 ...
- lintcode-15-全排列
全排列 给定一个数字列表,返回其所有可能的排列. 注意事项 你可以假设没有重复数字. 样例 给出一个列表[1,2,3],其全排列为: [ [1,2,3], [1,3,2], [2,1,3], [2,3 ...
- iOS开发开辟线程总结--NSThread
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- 第64天:CSS常用命名规范,有用!
CSS常用命名,必须记住 一.常用命名 标题:title 摘要:summary 箭头:arrow 商标:label 网站标志:logo 转角/圆角:corner 横幅广告:banner 子菜单:sub ...
- RT-thread内核之IO设备管理系统
RT-Thread系统的IO设备管理模块为上层应用提供了一个对设备进行访问的通用抽象接口,而对于下层设备来说则提供了底层设备驱动框架,并通过定义的数据结构对设备信息和底层设备驱动进行管理.从系统整体位 ...
- POJ3525:Most Distant Point from the Sea——题解
http://poj.org/problem?id=3525 题目大意:给一个逆时针序列的多边形点集,求其中可以画的最大半径的圆的半径. —————————————————————— 二分枚举半径长度 ...