数据结构&图论:欧拉游览树
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上剖分一 ...
随机推荐
- BZOJ 4176 Lucas的数论 莫比乌斯反演+杜教筛
题意概述:求,n<=10^9,其中d(n)表示n的约数个数. 分析: 首先想要快速计算上面的柿子就要先把d(ij)表示出来,有个神奇的结论: 证明:当且仅当a,b没有相同的质因数的时候我们统计其 ...
- POJ 3487 The Stable Marriage Problem(稳定婚姻问题 模版题)
Description The stable marriage problem consists of matching members of two different sets according ...
- 基于范围的for语句
一.关键点 1. 作用过程 遍历给定序列中的每个元素并对序列中的每个值执行某种操作. 2. 若要修改序列中元素的值,需将类型定义为引用 string s("Hello World!!!&qu ...
- 单源最短路——SPFA算法(Bellman-Ford算法队列优化)
spfa的算法思想(动态逼近法): 设立一个先进先出的队列q用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路 ...
- Java 变量和输入输出
一些重要知识 一个源文件里只能有一个public类,其它类数量不限.文件名与public类名相同 JAVA程序严格区分大小写 JAVA应用程序的执行入口是main方法固定写法:public stati ...
- Java容器之List接口
List 接口: 1. List 接口是 Collection 的子接口,实现 List 接口的容器类中的元素是有顺序的,而且可以重复: 2. List 容器中的元素都对应一个整数型的序号记载其在容器 ...
- 【Linux】- Ubuntu安装redis,并开启远程访问
Ubuntu16.04安装Redis 开启Redis远程访问的步骤: 1.注释掉redis配置文件中的,bind 127.0.0.1 sudo vi /etc/redis/redis.conf #注释 ...
- 完整和增量备份MySQL脚本
本文档采用mysqldump 对数据库进行备份,mysqldump 是采用SQL级别的备份机制,它将数据表导成 SQL脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法 ...
- C#窗口文件双击打开时出错
出错原因: 1. 修改了该窗口文件的.Designer.cs文件中:#region Windows 窗体设计器生成的代码这里面的代码,导致运行不正常. 为了传递数据,我在构造函数中增加了传递的值. 需 ...
- C#添加本地打印机
class Program { static void Main(string[] args) { const string printerName = "Print to file&quo ...