http://www.lydsy.com/JudgeOnline/problem.php?id=4817
lct+线段树+dfs序
操作1:access
操作2:u到根的-v到根的-lca到根的*2+1
操作3:查询线段树区间最大值
1A,嘎嘎嘎
#include<cmath>
#include<cstdio>
#include<iostream> using namespace std; #define max(x,y) ((x)>(y) ? (x) : (y)) #define N 100001 int n;
int front[N],to[N<<],nxt[N<<],tot; int id[N],dy[N],lst[N],tim;
int dep[N]; int lim,F[N][]; int mx[N<<],tag[N<<]; int root;
int fa[N],ch[N][];
bool rev[N]; int st[N],top; int ans; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs(int x)
{
id[x]=++tim;
dy[tim]=x;
dep[x]=dep[fa[x]]+;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x])
{
F[to[i]][]=fa[to[i]]=x;
dfs(to[i]);
}
lst[x]=tim;
} void build(int k,int l,int r)
{
if(l==r)
{
mx[k]=dep[dy[l]];
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
mx[k]=max(mx[k<<],mx[k<<|]);
} void down(int k)
{
mx[k<<]+=tag[k];
tag[k<<]+=tag[k];
mx[k<<|]+=tag[k];
tag[k<<|]+=tag[k];
tag[k]=;
} void change(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr)
{
mx[k]+=w;
tag[k]+=w;
return;
}
if(tag[k]) down(k);
int mid=l+r>>;
if(opl<=mid) change(k<<,l,mid,opl,opr,w);
if(opr>mid) change(k<<|,mid+,r,opl,opr,w);
mx[k]=max(mx[k<<],mx[k<<|]);
} void Change(int x,int w)
{
if(x==root) change(,,n,,n,w);
else if(id[x]>id[root] && id[x]<=lst[root]) change(,,n,id[x],lst[x],w);
else
{
int t=root,c=dep[root]-dep[x]-;
for(int i=lim;i>=;--i)
if(c&(<<i)) t=F[t][i];
if(id[t]>) change(,,n,,id[t]-,w);
if(lst[t]<n) change(,,n,lst[t]+,n,w);
}
} int query1(int k,int l,int r,int pos)
{
if(l==r) return mx[k];
if(tag[k]) down(k);
int mid=l+r>>;
if(pos<=mid) return query1(k<<,l,mid,pos);
return query1(k<<|,mid+,r,pos);
} void query2(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr)
{
ans=max(ans,mx[k]);
return;
}
if(tag[k]) down(k);
int mid=l+r>>;
if(opl<=mid) query2(k<<,l,mid,opl,opr);
if(opr>mid) query2(k<<|,mid+,r,opl,opr);
} void push_down(int x)
{
if(rev[x])
{
if(ch[x][]) rev[ch[x][]]^=;
if(ch[x][]) rev[ch[x][]]^=;
rev[x]^=;
}
} bool is_root(int x)
{
return ch[fa[x]][]!=x && ch[fa[x]][]!=x;
} bool get_son(int x)
{
return ch[fa[x]][]==x;
} void rotate(int x)
{
int y=fa[x],z=fa[y];
bool k=ch[y][]==x;
if(!is_root(y)) ch[z][ch[z][]==y]=x;
ch[y][k]=ch[x][k^]; ch[x][k^]=y;
fa[x]=z; fa[y]=x; fa[ch[y][k]]=y;
} void splay(int x)
{
st[top=]=x;
for(int i=x;!is_root(i);i=fa[i]) st[++top]=fa[i];
for(int i=top;i;--i) push_down(st[i]);
int y;
while(!is_root(x))
{
y=fa[x];
if(!is_root(y)) rotate(get_son(x)==get_son(y) ? x : y );
rotate(x);
}
} int find_root(int x)
{
push_down(x);
while(ch[x][])
{
x=ch[x][];
push_down(x);
}
return x;
} void access(int x)
{
int t=;
while(x)
{
splay(x);
if(ch[x][]) Change(find_root(ch[x][]),);
ch[x][]=t;
if(t) Change(find_root(t),-);
t=x; x=fa[x];
}
} int get_lca(int u,int v)
{
if(dep[u]<dep[v]) std::swap(u,v);
int d=dep[u]-dep[v];
for(int i=lim;i>=;--i)
if(d&(<<i)) u=F[u][i];
if(u==v) return u;
for(int i=lim;i>=;--i)
if(F[u][i]!=F[v][i]) u=F[u][i],v=F[v][i];
return F[u][];
} int main()
{
int m;
read(n); read(m);
lim=log(n)/log();
int u,v;
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
dfs();
for(int j=;j<=lim;++j)
for(int i=;i<=n;++i)
F[i][j]=F[F[i][j-]][j-];
build(,,n);
root=;
int ty;
int lca;
while(m--)
{
read(ty); read(u);
if(ty==) access(u);
else if(ty==)
{
read(v);
lca=get_lca(u,v);
printf("%d\n",query1(,,n,id[u])+query1(,,n,id[v])-query1(,,n,id[lca])*+);
}
else
{
ans=;
query2(,,n,id[u],lst[u]);
printf("%d\n",ans);
}
}
}