# 题解

$$d[a]-r[a]\leq r[b] - d[b]$$

# 代码1 - splay

#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
using namespace std;
typedef long long LL;
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=100005,INF=1.05e9,mod=1e9;
const double checkval=0.80;
namespace spl{
const int S=N*100;
int son[S][2],fa[S],val[S],size[S];
int cnt=0;
namespace cly{
int st[S],top=0;
inline int new_node(){
}
inline void Recover(int x){
st[++top]=x;
son[x][0]=son[x][1]=fa[x]=val[x]=size[x]=0;
}
}
using cly::new_node;
using cly::Recover;
#define ls son[x][0]
#define rs son[x][1]
int new_node(int v){
int x=new_node();
val[x]=v;
return x;
}
inline void pushup(int x){
size[x]=size[ls]+size[rs]+1;
}
inline int wson(int x){
return son[fa[x]][1]==x;
}
void rotate(int x){
int y=fa[x],z=fa[y],L=son[y][1]==x,R=L^1;
if (z)
son[z][son[z][1]==y]=x;
fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
son[y][L]=son[x][R],son[x][R]=y;
pushup(y),pushup(x);
}
void splay(int x){
for (int y=fa[x];fa[x];rotate(x),y=fa[x])
if (fa[y])
rotate(wson(x)==wson(y)?y:x);
}
inline void Ins(int &a,int v){
register int x=a,c=0;
int f=0;
while (x){
c++;
size[x]++;
f=x;
x=v<val[x]?ls:rs;
}
val[son[f][v>=val[f]]=x=new_node()]=v,fa[x]=f,size[x]=1;
if (!a||c>30)
splay(a=x);
}
int Query(int &rt,int v){
int ans=0,c=0;
register int x=rt,p=0;
while (x){
p=x,c++;
if (val[x]<=v)
ans+=size[ls]+1,x=rs;
else
x=ls;
}
if (p&&c>30)
splay(rt=p);
return ans;
}
void Remove(int x){
if (x)
Remove(ls),Remove(rs),Recover(x);
}
int id[N];
void Build(int &x,int L,int R,int f){
if (L>R)
return;
int mid=(L+R)>>1;
fa[x=id[mid]]=f;
Build(ls,L,mid-1,x);
Build(rs,mid+1,R,x);
pushup(x);
}
void Build(int &x,vector <int> &v){
if (v.empty())
return;
int n=0;
sort(v.begin(),v.end());
for (auto i : v)
id[++n]=new_node(i);
Build(x,1,n,0);
}
#undef ls
#undef rs
}
int Test,n;
LL ans=0;
vector <int> e[N];
int fa[N][20],depth[N],len[N];
int LCA(int x,int y){
if (depth[x]<depth[y])
swap(x,y);
Fod(i,16,0)
if (depth[x]-(1<<i)>=depth[y])
x=fa[x][i];
if (x==y)
return x;
Fod(i,16,0)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int Dis(int x,int y){
return len[x]+len[y]-2*len[LCA(x,y)];
}
int r[N];
namespace dt{
int fa[N],size[N],mxs[N],depth[N];
int rt[N],rtf[N];
int node_cnt=0;
void Init(){
clr(fa),clr(size),clr(mxs),clr(depth),clr(rt),clr(rtf);
depth[0]=-1,node_cnt++;
size[1]=1,mxs[1]=depth[1]=rt[1]=0;
spl::Ins(rt[1],0-r[1]);
}
int id[N],idc=0;
void dfs(int x,int pre,int d){
id[++idc]=x;
for (auto y : e[x])
if (y!=pre&&depth[y]>=d)
dfs(y,x,d);
}
int sz[N],msz[N],RT,Size;
void dfs2(int x,int pre){
sz[x]=1,msz[x]=0;
for (auto y : e[x])
if (y!=pre&&!size[y]){
dfs2(y,x);
sz[x]+=sz[y];
msz[x]=max(msz[x],sz[y]);
}
msz[x]=max(msz[x],Size-sz[x]);
if (!RT||msz[x]<msz[RT])
RT=x;
}
vector <int> id1,id2;
void dfs3(int x,int pre,int anc){
sz[x]=1;
id1.pb(Dis(x,anc)-r[x]);
if (fa[anc])
id2.pb(Dis(x,fa[anc])-r[x]);
for (auto y : e[x])
if (y!=pre&&!size[y])
dfs3(y,x,anc),sz[x]+=sz[y];
}
void build(int x,int f,int n){
RT=0,Size=n;
dfs2(x,0);
x=RT;
fa[x]=f,depth[x]=depth[f]+1,size[x]=n,mxs[x]=msz[x];
id1.clear(),id2.clear();
dfs3(x,0,x);
spl::Build(rt[x],id1);
spl::Build(rtf[x],id2);
for (auto y : e[x])
if (!size[y])
build(y,x,sz[y]);
}
void Rebuild(int x,int f){
idc=0;
dfs(x,0,depth[x]);
For(_t,1,idc){
int i=id[_t];
spl::Remove(rt[i]),spl::Remove(rtf[i]);
depth[i]=size[i]=fa[i]=mxs[i]=rt[i]=rtf[i]=0;
}
build(x,f,idc);
}
void Ins(int x,int f){
static vector <int> v;
fa[x]=f,depth[x]=depth[f]+1;
rt[x]=rtf[x]=0;
v.clear();
for (int i=x;i;i=fa[i]){
v.pb(i),size[i]++;
mxs[fa[i]]=max(mxs[fa[i]],size[i]);
spl::Ins(rt[i],Dis(i,x)-r[x]);
if (fa[i])
spl::Ins(rtf[i],Dis(fa[i],x)-r[x]);
}
node_cnt++;
reverse(v.begin(),v.end());
for (auto i : v)
if (mxs[i]>checkval*size[i]){
Rebuild(i,fa[i]);
break;
}
if (size[x]>1)
ans+=spl::Query(rt[x],r[x])-1;
for (int i=x,f,d;depth[i];i=f){
f=fa[i],d=Dis(f,x);
ans+=spl::Query(rt[f],r[x]-d)-spl::Query(rtf[i],r[x]-d);
}
}
}
int main(){
For(i,1,n){
if (!f){
dt::Init();
printf("%lld\n",ans);
continue;
}
assert(1<=f&&f<i);
e[i].pb(f),e[f].pb(i);
fa[i][0]=f;
For(j,1,16)
fa[i][j]=fa[fa[i][j-1]][j-1];
depth[i]=depth[f]+1;
len[i]=len[f]+c;
dt::Ins(i,f);
printf("%lld\n",ans);
}
return 0;
}


# 代码2 - Treap（非旋）

#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
using namespace std;
typedef long long LL;
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=100005,INF=1.05e9,mod=1e9;
const double checkval=0.80;
int randint(){
#ifdef windows
return (rand()<<15)^rand();
#else
return rand();
#endif
}
namespace Treap{
const int S=N*100;
int son[S][2],val[S],ckv[S],size[S];
int cnt=0;
namespace cly{
int st[S],top=0;
inline int new_node(){
}
inline void Recover(int x){
st[++top]=x,son[x][0]=son[x][1]=val[x]=size[x]=0;
}
}
#define ls son[x][0]
#define rs son[x][1]
int new_node(int v){
int x=cly::new_node();
val[x]=v,ckv[x]=randint(),size[x]=1;
return x;
}
void pushup(int x){
size[x]=size[ls]+size[rs]+1;
}
int Merge(int x,int y){
if (!x||!y)
return x+y;
if (ckv[x]<ckv[y]){
son[x][1]=Merge(son[x][1],y),pushup(x);
return x;
}
else {
son[y][0]=Merge(x,son[y][0]),pushup(y);
return y;
}
}
pair <int,int> Split(int x,int k){
if (!x)
return mp(0,0);
if (k<=size[ls]){
pair <int,int> p=Split(ls,k);
ls=p.se,pushup(x);
return mp(p.fi,x);
}
else {
pair <int,int> p=Split(rs,k-size[ls]-1);
rs=p.fi,pushup(x);
return mp(x,p.se);
}
}
int _Rank(int x,int v){
return x?(val[x]>v?_Rank(ls,v):size[ls]+1+_Rank(rs,v)):0;
}
int Rank(int x,int v){
return _Rank(x,v-1);
}
int Query(int x,int v){
return _Rank(x,v);
}
int id[N];
int tL[N],tR[N],lcnt,rcnt;
void Build(int &x,int L,int R){
if (L>R)
return;
int Mi=L;
For(i,L+1,R)
if (ckv[id[i]]<ckv[id[Mi]])
Mi=i;
swap(id[Mi],id[R]);
x=id[R];
lcnt=rcnt=0;
For(i,L,R-1)
if (val[id[i]]<=val[x])
tL[++lcnt]=id[i];
else
tR[++rcnt]=id[i];
int c=L-1;
For(i,1,lcnt)
id[++c]=tL[i];
int mid=c;
For(i,1,rcnt)
id[++c]=tR[i];
Build(ls,L,mid);
Build(rs,mid+1,R-1);
pushup(x);
}
void Build(int &x,vector <int> &v){
if (v.empty())
return;
int n=0;
for (auto i : v)
id[++n]=new_node(i);
Build(x,1,n);
}
void Ins(int &x,int v){
pair <int,int> p=Split(x,_Rank(x,v));
x=Merge(p.fi,Merge(new_node(v),p.se));
}
void Remove(int x){
if (x)
Remove(ls),Remove(rs),cly::Recover(x);
}
#undef ls
#undef rs
}
int Test,n;
LL ans=0;
vector <int> e[N];
int fa[N][20],depth[N],len[N];
int LCA(int x,int y){
if (depth[x]<depth[y])
swap(x,y);
Fod(i,16,0)
if (depth[x]-(1<<i)>=depth[y])
x=fa[x][i];
if (x==y)
return x;
Fod(i,16,0)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int Dis(int x,int y){
return len[x]+len[y]-2*len[LCA(x,y)];
}
int r[N];
namespace dt{
int fa[N],size[N],mxs[N],depth[N];
int rt[N],rtf[N];
int node_cnt=0;
void Init(){
clr(fa),clr(size),clr(mxs),clr(depth),clr(rt),clr(rtf);
depth[0]=-1,node_cnt++;
size[1]=1,mxs[1]=depth[1]=rt[1]=0;
Treap::Ins(rt[1],0-r[1]);
}
int id[N],idc=0;
void dfs(int x,int pre,int d){
id[++idc]=x;
for (auto y : e[x])
if (y!=pre&&depth[y]>=d)
dfs(y,x,d);
}
int sz[N],msz[N],RT,Size;
void dfs2(int x,int pre){
sz[x]=1,msz[x]=0;
for (auto y : e[x])
if (y!=pre&&!size[y]){
dfs2(y,x);
sz[x]+=sz[y];
msz[x]=max(msz[x],sz[y]);
}
msz[x]=max(msz[x],Size-sz[x]);
if (!RT||msz[x]<msz[RT])
RT=x;
}
vector <int> id1,id2;
void dfs3(int x,int pre,int anc){
sz[x]=1;
id1.pb(Dis(x,anc)-r[x]);
if (fa[anc])
id2.pb(Dis(x,fa[anc])-r[x]);
for (auto y : e[x])
if (y!=pre&&!size[y])
dfs3(y,x,anc),sz[x]+=sz[y];
}
void build(int x,int f,int n){
RT=0,Size=n;
dfs2(x,0);
x=RT;
fa[x]=f,depth[x]=depth[f]+1,size[x]=n,mxs[x]=msz[x];
id1.clear(),id2.clear();
dfs3(x,0,x);
Treap::Build(rt[x],id1);
Treap::Build(rtf[x],id2);
for (auto y : e[x])
if (!size[y])
build(y,x,sz[y]);
}
void Rebuild(int x,int f){
idc=0;
dfs(x,0,depth[x]);
For(_t,1,idc){
int i=id[_t];
Treap::Remove(rt[i]),Treap::Remove(rtf[i]);
depth[i]=size[i]=fa[i]=mxs[i]=rt[i]=rtf[i]=0;
}
build(x,f,idc);
}
void Ins(int x,int f){
static vector <int> v;
fa[x]=f,depth[x]=depth[f]+1;
rt[x]=rtf[x]=0;
v.clear();
for (int i=x;i;i=fa[i]){
v.pb(i),size[i]++;
mxs[fa[i]]=max(mxs[fa[i]],size[i]);
Treap::Ins(rt[i],Dis(i,x)-r[x]);
if (fa[i])
Treap::Ins(rtf[i],Dis(fa[i],x)-r[x]);
}
node_cnt++;
reverse(v.begin(),v.end());
for (auto i : v)
if (mxs[i]>checkval*size[i]){
Rebuild(i,fa[i]);
break;
}
if (size[x]>1)
ans+=Treap::Query(rt[x],r[x])-1;
for (int i=x,f,d;depth[i];i=f){
f=fa[i],d=Dis(f,x);
ans+=Treap::Query(rt[f],r[x]-d)-Treap::Query(rtf[i],r[x]-d);
}
}
}
int main(){
srand(_SEED_);
For(i,1,n){
if (!f){
dt::Init();
printf("%lld\n",ans);
continue;
}
e[i].pb(f),e[f].pb(i);
fa[i][0]=f;
For(j,1,16)
fa[i][j]=fa[fa[i][j-1]][j-1];
depth[i]=depth[f]+1;
len[i]=len[f]+c;
dt::Ins(i,f);
printf("%lld\n",ans);
}
return 0;
}


posted @ 2019-03-03 22:33 -zhouzhendong- 阅读(...) 评论(...) 编辑 收藏