• BZOJ4551


    Portal

    Description

    给出一棵(n(nleq10^5))个点的以(1)为根的有根树,进行(Q(Qleq10^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
    ",query(u));
        }
        return 0;
    }
    

    P.S.

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

  • 相关阅读:
    Web服务器和应用服务器的区别
    Java程序员应该知道的10个调试技巧
    java快捷键个人总结
    MySQL主从复制与读写分离
    CDN(内容分发网络)技术原理
    淘宝技术发展
    Monitor a Folder using Java
    Android eclipse中程序调试
    在学校教学Java是有争议的
    LINUX ubuntu 12.04 svn 1.6.7 苦逼的装了一个下午啊!! 绝对详细!正确!不吭爹!!
  • 原文地址:https://www.cnblogs.com/VisJiao/p/BZOJ4551.html
Copyright © 2020-2023  润新知