BZOJ4551 - [TJOI2016]树

Portal

Description

给出一棵\(n(n\leq10^5)\)个点的以\(1\)为根的有根树,进行\(Q(Q\leq10^5)\)次操作:

  • 标记一个点\(x\)
  • 询问\(x\)的祖先中(包括\(x\)),距\(x\)最近的被标记的点。

Solution

用lct搞一搞就行啦。标记点\(x\)splay(x),询问时access(x)后求最深的被标记点即可。

时间复杂度\(O(Qlogn)\)

Code

//树
#include <cstdio>
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
int const N=1e5+10;
int n,Q;
int cnt,h[N];
struct edge{int v,nxt;} ed[N<<1];
inline void edAdd(int u,int v)
{
    cnt++; ed[cnt].v=v,ed[cnt].nxt=h[u],h[u]=cnt;
    cnt++; ed[cnt].v=u,ed[cnt].nxt=h[v],h[v]=cnt;
}
int fa[N],ch[N][2]; int sum[N],val[N];
void bldTree(int u)
{
    for(int i=h[u];i;i=ed[i].nxt)
        if(ed[i].v!=fa[u]) fa[ed[i].v]=u,bldTree(ed[i].v);
}
inline int wh(int p) {return p==ch[fa[p]][1];}
inline int notRt(int p) {return p==ch[fa[p]][wh(p)];}
inline void update(int p) {sum[p]=sum[ch[p][0]]+val[p]+sum[ch[p][1]];}
inline void rotate(int p)
{
    int q=fa[p],r=fa[q],w=wh(p);
    fa[p]=r; if(notRt(q)) ch[r][wh(q)]=p;
    fa[ch[q][w]=ch[p][w^1]]=q;
    fa[ch[p][w^1]=q]=p;
    update(q),update(p);
}
void splay(int p)
{
    for(int q=fa[p];notRt(p);rotate(p),q=fa[p]) if(notRt(q)) rotate(wh(p)^wh(q)?p:q);
}
int rnk(int rt,int x)
{
    int p=rt;
    while(true)
        if(x<=sum[ch[p][0]]) p=ch[p][0];
        else if(x<=sum[ch[p][0]]+val[p]) return p;
        else x-=sum[ch[p][0]]+val[p],p=ch[p][1];
}
void access(int p) {for(int q=0;p;q=p,p=fa[p]) splay(p),ch[p][1]=q,update(p);}
int query(int p) {access(p),splay(p); return rnk(p,sum[p]);}
int main()
{
    n=read(),Q=read();
    for(int i=1;i<=n-1;i++) edAdd(read(),read());
    fa[1]=0,bldTree(1); val[1]=1,update(1);
    for(int i=1;i<=Q;i++)
    {
        char opt=gc(); while(opt!='C'&&opt!='Q') opt=gc();
        int u=read();
        if(opt=='C') val[u]=1,update(u),splay(u);
        else printf("%d\n",query(u));
    }
    return 0;
}

P.S.

这题原数据水到暴力AC...没错就是每次跳fa

posted @ 2018-04-01 20:09  VisJiao  阅读(117)  评论(0编辑  收藏  举报