diff --git a/content/data-structure/SegmentTreeBeats.hpp b/content/data-structure/SegmentTreeBeats.hpp index 599b921..827633f 100644 --- a/content/data-structure/SegmentTreeBeats.hpp +++ b/content/data-structure/SegmentTreeBeats.hpp @@ -1,4 +1,5 @@ #pragma once +#include "../template/Header.hpp" /** * Author: Teetat T. diff --git a/content/data-structure/StaticTopTree.hpp b/content/data-structure/StaticTopTree.hpp new file mode 100644 index 0000000..aeb7a94 --- /dev/null +++ b/content/data-structure/StaticTopTree.hpp @@ -0,0 +1,159 @@ +#pragma once +#include "../template/Header.hpp" + +/** + * Author: Teetat T. + * Date: 2024-08-17 + * License: CC0 + * Description: Static Top Tree + * Status: Tested + */ + +enum Type{Compress,Rake,AddEdge,AddVertex,Vertex}; + +struct StaticTopTree{ + int n,node_id; + int root,stt_root; + vector> &adj; + vector hv; + vector lch,rch,par; + vector type; + StaticTopTree(vector> &_adj,int _root):adj(_adj){ + n=adj.size(); + root=_root; + node_id=n; + hv.assign(n,-1); + lch.assign(4*n,-1); + rch.assign(4*n,-1); + par.assign(4*n,-1); + type.assign(4*n,Type::Vertex); + dfs(root); + stt_root=compress(root).first; + } + int dfs(int u){ + int mx=0,sz=1; + for(auto v:adj[u]){ + int x=dfs(v); + sz+=x; + if(x>mx){ + hv[u]=v; + mx=x; + } + } + return sz; + } + int add(int i,int l,int r,Type t){ + if(i==-1)i=node_id++; + lch[i]=l,rch[i]=r,par[i]=-1,type[i]=t; + if(l!=-1)par[l]=i; + if(r!=-1)par[r]=i; + return i; + } + pair merge(vector> a,Type t){ + if(a.size()==1)return a[0]; + int tot=0; + vector> l,r; + for(auto [i,s]:a)tot+=s; + for(auto [i,s]:a){ + if(tot>s)l.emplace_back(i,s); + else r.emplace_back(i,s); + tot-=s*2; + } + auto [i,si]=merge(l,t); + auto [j,sj]=merge(r,t); + return {add(-1,i,j,t),si+sj}; + } + pair compress(int i){ + vector> a{add_vertex(i)}; + while(hv[i]!=-1)a.emplace_back(add_vertex(i=hv[i])); + return merge(a,Type::Compress); + } + pair rake(int i){ + vector> a; + for(auto j:adj[i])if(j!=hv[i])a.emplace_back(add_edge(j)); + return a.empty()?make_pair(-1,0):merge(a,Type::Rake); + } + pair add_edge(int i){ + auto [j,s]=compress(i); + return {add(-1,j,-1,Type::AddEdge),s}; + } + pair add_vertex(int i){ + auto [j,s]=rake(i); + return {add(i,j,-1,j==-1?Type::Vertex:Type::AddVertex),s+1}; + } +}; + +const int N=2e5+5; + +int n,q; +ll a[N]; +vector> adj; + +using Path = pair; +using Point = ll; + +Path compress(Path p,Path ch){ + auto [a,b]=ch; + auto [c,d]=p; + return {a*c%MOD,(b*c+d)%MOD}; +} + +Point rake(Point l,Point r){ + return l*r%MOD; +} + +Path add_vertex(Point x,int i){ + return {x,a[i]}; +} + +Point add_edge(Path x){ + return x.second; +} + +Path vertex(int i){ + return {1LL,a[i]}; +} + +Path path[4*N]; +Point point[4*N]; + +void example(){ + cin.tie(nullptr)->sync_with_stdio(false); + cin >> n >> q; + adj.resize(n); + for(int i=1;i> p; + adj[p-1].emplace_back(i); + } + for(int i=0;i> a[i]; + StaticTopTree stt(adj,0); + auto update=[&](int i){ + if(stt.type[i]==Type::Compress){ + path[i]=compress(path[stt.lch[i]],path[stt.rch[i]]); + }else if(stt.type[i]==Type::Rake){ + point[i]=rake(point[stt.lch[i]],point[stt.rch[i]]); + }else if(stt.type[i]==Type::AddVertex){ + path[i]=add_vertex(point[stt.lch[i]],i); + }else if(stt.type[i]==Type::AddEdge){ + point[i]=add_edge(path[stt.lch[i]]); + }else{ + path[i]=vertex(i); + } + }; + function dfs=[&](int u){ + if(u==-1)return; + dfs(stt.lch[u]); + dfs(stt.rch[u]); + update(u); + }; + dfs(stt.stt_root); + while(q--){ + int v,x; + cin >> v >> x; + v--; + a[v]=x; + for(;v!=-1;v=stt.par[v])update(v); + cout << path[stt.stt_root].second << "\n"; + } +} \ No newline at end of file diff --git a/content/data-structure/chapter.tex b/content/data-structure/chapter.tex index bc5f3ca..2d2981a 100644 --- a/content/data-structure/chapter.tex +++ b/content/data-structure/chapter.tex @@ -16,3 +16,4 @@ \chapter{Data Structures} \kactlimport{LazyReversibleSplayTree.hpp} \kactlimport{LinkCutTreeBase.hpp} \kactlimport{LazyLinkCutTree.hpp} +\ksactlimport{StaticTopTree.hpp} \ No newline at end of file