[SDOI2016]bzoj 4817 树点涂色 - LCT - 线段树

和之前写的LCT维护子树真是小巫见大巫了……

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<utility>
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
#define N 100010
#define LOG 20
#define mp make_pair
#define sec second
using namespace std;
typedef pair<int,int> pii;
pii val[N],mn[N];
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
    int to,pre;
}e[N<<1];int fa[N],pf[N],ch[N][2],up[N][LOG];
int Log[N],d[N],h[N],etop,in[N],out[N],tm[N],dfc;
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
struct segment{
    int l,r,pt,mx;
    segment *ch[2];
}*rt;
inline int push_up(segment* &rt) { return rt->mx=max(rt->ch[0]->mx,rt->ch[1]->mx); }
inline int update_tags(segment* &rt,int v) { return rt->mx+=v,rt->pt+=v; }
inline int push_down(segment* &rt)
{
    update_tags(rt->ch[0],rt->pt),
    update_tags(rt->ch[1],rt->pt);
    return rt->pt=0;
}
int build(segment* &rt,int l,int r)
{
    rt=new segment,rt->l=l,rt->r=r,rt->pt=0;
    if(l==r) return rt->mx=d[tm[l]];int mid=(l+r)>>1;
    return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r),push_up(rt);
}
int update(segment* &rt,int s,int t,int v)
{
    int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(s<=l&&r<=t) return update_tags(rt,v);
    if(rt->pt) push_down(rt);
    if(s<=mid) update(rt->ch[0],s,t,v);
    if(mid<t) update(rt->ch[1],s,t,v);
    return push_up(rt);
}
int query(segment* &rt,int s,int t)
{
    int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(s<=l&&r<=t) return rt->mx;int ans=0;
    if(rt->pt) push_down(rt);
    if(s<=mid) ans=max(ans,query(rt->ch[0],s,t));
    if(mid<t) ans=max(ans,query(rt->ch[1],s,t));
    return ans;
}
inline int query(segment* &rt,int p) { return query(rt,p,p); }
inline int gw(int x) { return ch[fa[x]][1]==x; }
inline int push_up(int x) { return mn[x]=min(val[x],min(mn[ch[x][0]],mn[ch[x][1]])),0; }
inline int setc(int x,int y,int z)
{   if(!x) return fa[y]=x;ch[x][z]=y;if(y) fa[y]=x;return push_up(x);   }
inline int rotate(int x)
{
    int y=fa[x],z=fa[y],a=gw(x),b=gw(y),c=ch[x][a^1];
    return swap(pf[x],pf[y]),setc(y,c,a),setc(x,y,a^1),setc(z,x,b);
}
inline int splay(int x,int tar=0)
{
    for(;fa[x]^tar;rotate(x))
        if(fa[fa[x]]^tar) rotate(gw(fa[x])==gw(x)?fa[x]:x);
    return 0;
}
inline int expose(int x)
{
    splay(x);int y=ch[x][1];if(!y) return 0;
    int z=mn[y].sec;update(rt,in[z],out[z],1);
    return pf[y]=x,fa[y]=ch[x][1]=0;
}
inline int splice(int x)
{
    splay(x);int y=pf[x];if(!y) return 0;
    int z=mn[x].sec;
    expose(y),update(rt,in[z],out[z],-1);
    return pf[x]=0,setc(y,x,1),splay(x),1;
}
inline int access(int x) { expose(x);while(splice(x));return splay(x); }
int dfs(int x,int f=0)
{
    up[x][0]=pf[x]=f,tm[in[x]=++dfc]=x,
    d[x]=d[f]+1,val[x]=mn[x]=mp(d[x],x);
    for(int i=1;i<=Log[d[x]];i++)
        up[x][i]=up[up[x][i-1]][i-1];
    for(int i=h[x],y;i;i=e[i].pre)
        if((y=e[i].to)^f) dfs(y,x);
    return out[x]=dfc;
}
int getLCA(int x,int y)
{
    if(d[x]<d[y]) swap(x,y);
    for(int i=Log[d[x]];i>=0;i--)
        if(d[up[x][i]]>=d[y]) x=up[x][i];
    if(x==y) return x;
    for(int i=Log[d[x]];i>=0;i--)
        if(up[x][i]^up[y][i])
            x=up[x][i],y=up[y][i];
    return up[x][0];
}
int main()
{
    int n=inn(),m=inn();
    for(int i=1,x,y;i<n;i++)
        x=inn(),y=inn(),add_edge(x,y),add_edge(y,x);
    for(int i=2;i<N;i++) Log[i]=Log[i>>1]+1;
    mn[0]=val[0]=mp(N,0),dfs(1),build(rt,1,n);
//  for(int i=1;i<=n;i++) debug(i)sp,debug(pf[i])sp,debug(d[i])sp,debug(in[i])ln;
    while(m--)
    {
        int opt=inn(),x,y,c;
        if(opt==1) access(inn());
        else if(opt==2) x=inn(),y=inn(),c=getLCA(x,y),//debug(c)ln,
            printf("%d\n",query(rt,in[x])+query(rt,in[y])-2*query(rt,in[c])+1);
        else x=inn(),printf("%d\n",query(rt,in[x],out[x]));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81360844
今日推荐