数据结构&图论:欧拉游览树
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上剖分一 ...
随机推荐
- JS判断是IOS还是Android以及如何解决h5打包后在ios下内容与状态栏重叠问题
h5打包后在ios下内容与状态栏重叠问题: 1:知道设备的类型: var u = navigator.userAgent, app = navigator.appVersion; var isAndr ...
- Coursera:Internet History ,Techornology and Security
WEEK1 War Time Computing and Communication Bletchley Park 布莱彻利庄园:a top-secret code breaking effort b ...
- 福州大学软工1816 | K班 第一次作业
(一)回想一下你初入大学时对计算机专业的畅想 (1)当初你是如何做出选择计算机专业的决定的? 本身对于计算机感兴趣.高考完之后翻了书,对于物理数学等基础学科兴趣不大,对金融等商科几乎毫无了解,再加上当 ...
- lintcode-182-删除数字
182-删除数字 给出一个字符串 A, 表示一个 n 位正整数, 删除其中 k 位数字, 使得剩余的数字仍然按照原来的顺序排列产生一个新的正整数. 找到删除 k 个数字之后的最小正整数. N < ...
- 3DMAX2016安装教程【图文】
下载安装包之后,双击setup.exe. 下面是安装图片教程: 点击安装 点击下一步. 如图输入序列号和产品密钥. 填写安装路径,然后下一步. 开始安装,等待. 安装成功.
- 用SC命令 添加或删除windows服务提示OpenSCManager 失败5 拒绝访问
在安装命令行中安装 windowsOpenSCManager 失败5 的错误,原因是当前用户的权限不足,需要做的是在注册表 HKEY_LOCAL_MACHINE\Software\Microsof ...
- Android api level对照表
转自:blog.csdn.net/lihenair/article/details/49869299 Platform Version API Level VERSION_CODE Notes And ...
- C#中的反射和扩展方法的运用
前段时间做了一个练手的小项目,采用的是三层架构,也就是Models,IDAL,DAL,BLL 和 Web , 在DAL层中各个类中有一个方法比较常用,那就是 RowToClass ,顾名思义,也就是将 ...
- HTML5 iframe sandbox javascript getTime
1 1 HTML5 iframe sandbox 1 1 <!DOCTYPE html> <html> <body> <iframe src="de ...
- 【Python】面向对象--类的特殊成员方法
类的特殊成员方法 1. __doc__ 表示类的描述信息 class Func(object): '''__doc__方法是用来打印类的描述信息''' def tell(self): pass def ...