码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ4551 - [TJOI2016]树

时间:2018-04-01 20:49:03      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:mat   复杂度   online   stdin   not   div   add   gpo   include   

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

BZOJ4551 - [TJOI2016]树

标签:mat   复杂度   online   stdin   not   div   add   gpo   include   

原文地址:https://www.cnblogs.com/VisJiao/p/BZOJ4551.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!