bzoj千题计划275:bzoj4817: [Sdoi2017]树点涂色

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<<1],nxt[N<<1],tot;

int id[N],dy[N],lst[N],tim;
int dep[N];

int lim,F[N][17];

int mx[N<<2],tag[N<<2];

int root;
int fa[N],ch[N][2];
bool rev[N];

int st[N],top;

int ans;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; 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]]+1;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=fa[x])
        {
            F[to[i]][0]=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>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    mx[k]=max(mx[k<<1],mx[k<<1|1]);
}

void down(int k)
{
    mx[k<<1]+=tag[k];
    tag[k<<1]+=tag[k];
    mx[k<<1|1]+=tag[k];
    tag[k<<1|1]+=tag[k];
    tag[k]=0;
}

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>>1;
    if(opl<=mid) change(k<<1,l,mid,opl,opr,w);
    if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,w);
    mx[k]=max(mx[k<<1],mx[k<<1|1]);
}

void Change(int x,int w)
{
    if(x==root) change(1,1,n,1,n,w);
    else if(id[x]>id[root] && id[x]<=lst[root]) change(1,1,n,id[x],lst[x],w);
    else
    {
        int t=root,c=dep[root]-dep[x]-1;
        for(int i=lim;i>=0;--i)
            if(c&(1<<i)) t=F[t][i];
        if(id[t]>1) change(1,1,n,1,id[t]-1,w);
        if(lst[t]<n) change(1,1,n,lst[t]+1,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>>1;
    if(pos<=mid) return query1(k<<1,l,mid,pos);
    return query1(k<<1|1,mid+1,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>>1;
    if(opl<=mid) query2(k<<1,l,mid,opl,opr);
    if(opr>mid) query2(k<<1|1,mid+1,r,opl,opr);
}

void push_down(int x)
{
    if(rev[x])
    {
        if(ch[x][0]) rev[ch[x][0]]^=1;
        if(ch[x][1]) rev[ch[x][1]]^=1;
        rev[x]^=1;
    }
}

bool is_root(int x)
{
    return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}

bool get_son(int x)
{
    return ch[fa[x]][1]==x;
}
    
void rotate(int x)
{
    int y=fa[x],z=fa[y];
    bool k=ch[y][1]==x;
    if(!is_root(y)) ch[z][ch[z][1]==y]=x;
    ch[y][k]=ch[x][k^1]; ch[x][k^1]=y;
    fa[x]=z; fa[y]=x; fa[ch[y][k]]=y;
}

void splay(int x)
{
    st[top=1]=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][0])
    {
        x=ch[x][0];
        push_down(x);
    }
    return x;
}

void access(int x)
{
    int t=0;
    while(x)
    {
        splay(x);
        if(ch[x][1]) Change(find_root(ch[x][1]),1);
        ch[x][1]=t;
        if(t) Change(find_root(t),-1);
        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>=0;--i)
        if(d&(1<<i)) u=F[u][i];
    if(u==v) return u;
    for(int i=lim;i>=0;--i)
        if(F[u][i]!=F[v][i]) u=F[u][i],v=F[v][i];
    return F[u][0];
}

int main()
{
    int m;
    read(n); read(m);
    lim=log(n)/log(2);
    int u,v;
    for(int i=1;i<n;++i)
    {
        read(u); read(v);
        add(u,v);
    }
    dfs(1);
    for(int j=1;j<=lim;++j)
        for(int i=1;i<=n;++i)
            F[i][j]=F[F[i][j-1]][j-1];
    build(1,1,n);
    root=1;
    int ty;
    int lca;
    while(m--)
    {
        read(ty); read(u);
        if(ty==1) access(u);
        else if(ty==2) 
        {
            read(v);
            lca=get_lca(u,v);
            printf("%d\n",query1(1,1,n,id[u])+query1(1,1,n,id[v])-query1(1,1,n,id[lca])*2+1);
        }
        else 
        {
            ans=0;
            query2(1,1,n,id[u],lst[u]);
            printf("%d\n",ans);
        }
    }
}

 

posted @ 2018-03-12 20:29  TRTTG  阅读(200)  评论(0编辑  收藏  举报