ETT(Eular Tour Tree)是一种维护有根树的数据结构,支持以下操作
- 修改一个点的点权
- 子树修改
- 单点查询
- 点到根路径查询
- 修改一个点的父亲
据说可以支持换根,但用的不多而且据说很难写,所以似乎失传了(
其实没啥技术含量,顾名思义就是维护一棵树的欧拉序。
欧拉序指在 dfs 开始和结束时分别将当前点加入序列中,也称括号序。
用区间平衡树维护这个欧拉序。
平衡树不写 treap ,根本不是人
每个点第一次插入的权值为题目给定的权值,第二次插入时取相反数,要在平衡树上记录下这个符号,并记录下 每个原树上的点 两次插入时 在平衡树上的点 的编号。
对treap额外维护平衡树上的父结点 fa,然后可以找到给定编号的结点在平衡树上的排名。
单点操作直接搞就可以了。
因为欧拉序上一个子树对应的是一个括号,子树修改时直接修改这个括号的区间。注意每个点要分别乘上自己的符号,可以通过记录平衡树的子树的符号之和实现。
对于链查询,不难看出是这个点第一次出现的位置的前缀和,直接查询即可。
修改父亲直接把整个括号提出来**新父亲第一次位置的后面。
复杂度是 O ( n log n ) O(n\log n) O(nlogn),跑得比较慢
模板题
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> #include <cstdlib> #include <cassert> #define MAXN #define MAXM using namespace std; inline char gal() {
char c=getchar(); while (!isalpha(c)) c=getchar(); return c; } inline int read() {
int ans=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } typedef long long ll; vector<int> e[MAXN]; int w[MAXN]; int sig[MAXN],ind[MAXN],siz[MAXN],rad[MAXN],ch[MAXN][2],fa[MAXN],tot; ll val[MAXN],sum[MAXN],lzy[MAXN]; inline int newnode(int v,int type) {
++tot,siz[tot]=1,sum[tot]=val[tot]=v*type,sig[tot]=ind[tot]=type,rad[tot]=rand(); return tot; } inline void update(int x) {
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1,ind[x]=ind[ch[x][0]]+ind[ch[x][1]]+sig[x]; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x]; } inline void pushlzy(int x,ll v){
val[x]+=sig[x]*v,sum[x]+=v*ind[x],lzy[x]+=v;} inline void pushdown(int x) {
if (lzy[x]) {
if (ch[x][0]) pushlzy(ch[x][0],lzy[x]); if (ch[x][1]) pushlzy(ch[x][1],lzy[x]); lzy[x]=0; } } int merge(int x,int y) {
if (!x||!y) return x|y; pushdown(x),pushdown(y); if (rad[x]<rad[y]) return ch[x][1]=merge(ch[x][1],y),ch[x][1]&&(fa[ch[x][1]]=x),update(x),x; return ch[y][0]=merge(x,ch[y][0]),ch[y][0]&&(fa[ch[y][0]]=y),update(y),y; } void split(int x,int k,int& l,int& r) {
if (!x) return (void)(l=r=0); pushdown(x); if (k<=siz[ch[x][0]]) split(ch[x][0],k,l,r),fa[ch[x][0]]=0,ch[x][0]=r,r&&(fa[r]=x),update(x),r=x; else split(ch[x][1],k-siz[ch[x][0]]-1,l,r),fa[ch[x][1]]=0,ch[x][1]=l,l&&(fa[l]=x),update(x),l=x; } int rt,l[MAXN],r[MAXN]; inline void modify(int l,int r,int v) {
int a,b,c,d; split(rt,l-1,a,d); split(d,r-l+1,b,c); pushlzy(b,v); rt=merge(merge(a,b),c); } inline int getrk(int x) {
int f=1,ans=0; while (x) {
if (f) ans+=siz[ch[x][0]]+1; f=(ch[fa[x]][1]==x),x=fa[x]; } return ans; } void dfs(int u) {
int t; t=merge(rt,l[u]=newnode(w[u],1)),rt=t; for (int i=0;i<(int)e[u].size();i++) dfs(e[u][i]); t=merge(rt,r[u]=newnode(w[u],-1)),rt=t; } int main() {
int n=read(); for (int i=2;i<=n;i++) e[read()].push_back(i); for (int i=1;i<=n;i++) w[i]=read(); dfs(1); for (int T=read();T;T--) {
char op=gal(); if (op=='Q') {
int a,b; split(rt,getrk(l[read()]),a,b); printf("%lld\n",sum[a]); rt=merge(a,b); } if (op=='C') {
int x,y; x=read(),y=read(); int a,b,c,d,e; split(rt,getrk(l[x])-1,a,d); split(d,getrk(r[x]),b,c); e=merge(a,c); split(e,getrk(l[y]),a,c); rt=merge(merge(a,b),c); } if (op=='F') {
int x,v; x=read(),v=read(); modify(getrk(l[x]),getrk(r[x]),v); } } return 0; }
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/68828.html