zoukankan      html  css  js  c++  java
  • bzoj 3720: Gty的妹子树 块状树

    3720: Gty的妹子树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 412  Solved: 153
    [Submit][Status]

    Description

    我曾在弦歌之中听过你,

    檀板声碎,半出折子戏。

    舞榭歌台被风吹去,

    岁月深处尚有余音一缕……


    Gty神(xian)犇(chong)从来不缺妹子……

    他来到了一棵妹子树下,发现每个妹子有一个美丽度……

    由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。

    他想知道某个子树中美丽度大于k的妹子个数。

    某个妹子的美丽度可能发生变化……

    树上可能会出现一只新的妹子……


    维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。

    支持以下操作:

    0 u x          询问以u为根的子树中,严格大于x的值的个数。(u^=lastans,x^=lastans)

    1 u x          把u节点的权值改成x。(u^=lastans,x^=lastans)

    2 u x          添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u^=lastans,x^=lastans)

    最开始时lastans=0。

    Input

    输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。

    接下来n-1行,每行2个整数u,v,为树上的一条无向边。

    任何时刻,树上的任何权值大于等于0,且两两不同。

    接下来1行,包括n个整数wi,表示初始时每个节点的权值。

    接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。

    接下来m行,每行包括三个整数 op,u,v:

    op,u,v的含义见题目描述。

    保证题目涉及的所有数在int内。

    Output

    对每个op=0,输出一行,包括一个整数,意义见题目描述。

    Sample Input

    2
    1 2
    10 20
    1
    0 1 5

    Sample Output

    2

    HINT

    Source

      块状树,网上很多题解,这里就不说了。一般都是把整块的排序,非整块的不排,而我直接套了的一个平衡树,应该还是要快一点吧。  

      写的时候一直T,结果发现是忘记size++,导致整棵树只有一块,居然还跑的很快,随机数据2s就能跑过。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    #define MAXN 61000
    #define MAXB 100
    #define MAXV MAXN
    #define MAXE MAXN*2
    #define MAXT MAXN*2
    int L[MAXT],R[MAXT],S[MAXT],V[MAXT];
    int topt_sbt;
    #define update(now) S[now]=S[L[now]]+S[R[now]]+1;
    inline int nextInt()
    {
            register char ch;
            register int x=0;
            while (ch=getchar(),ch<'0' || ch>'9');
            while (x=x*10+ch-'0',ch=getchar(),ch<='9' && ch>='0');
            return x;
    }
    inline void r_rotate(register int &now)
    {
            register int t=L[now];
            L[now]=R[t];update(now);
            R[t]=now;update(t);
            now=t;
    }
    inline void l_rotate(register int &now)
    {
            register int t=R[now];
            R[now]=L[t];update(now);
            L[t]=now;update(t);
            now=t;
    }
    void maintain(register int &now)
    {
            if (S[L[L[now]]]>S[R[now]])
            {
                    r_rotate(now);
                    maintain(L[now]);
                //    maintain(R[now]);
                    maintain(now);
                    return ;
            }
            if (S[R[R[now]]]>S[L[now]])
            {
                    l_rotate(now);
                    maintain(R[now]);
                //    maintain(L[now]);
                    maintain(now);
                    return ;
            }
            if (S[L[R[now]]]>S[L[now]])
            {
                    r_rotate(R[now]);
                    l_rotate(now);
                    maintain(L[now]);
                    maintain(R[now]);
                    maintain(now);
                    return ;
            }
            if (S[R[L[now]]]>S[R[now]])
            {
                    l_rotate(L[now]);
                    r_rotate(now);
                    maintain(L[now]);
                    maintain(R[now]);
                    maintain(now);
                    return ;
            }
    }
    void Insert(register int &now,int v)
    {
            if (!now)
            {
                    now=++topt_sbt;
                    V[now]=v;
                    S[now]=1;
                    return ;
            }
            if (v<V[now])
                    Insert(L[now],v);
            else
                    Insert(R[now],v);
            update(now);
            maintain(now);
            return ;
    }
    void Erase(register int &now,int v)
    {
            if (!now)return;
            if (V[now]==v)
            {
                    if (!L[now] && !R[now])now=0;
                    else
                    {
                            if (!L[now])now=R[now];
                            else if (!R[now])now=L[now];
                            else
                            {
                                    r_rotate(now);
                                    Erase(R[now],v);
                            }
                            update(now);
                            maintain(now);
                    }
                    return ;
            }
            if (v<V[now])Erase(L[now],v);
            else Erase(R[now],v);
            update(now);
            maintain(now);
    }
    int Count_greater(int now,int v)
    {
            if (!now)return 0;
            return (V[now]>v)?S[R[now]]+1+Count_greater(L[now],v):Count_greater(R[now],v);
    }
    void Scan(int now)
    {
            if (!now)
                    return ;
            Scan(L[now]);
            printf("%d ",V[now]);
            Scan(R[now]);
    }
    struct Edge
    {
            int np;
            Edge *next;
    }E[MAXE*2],*V1[MAXV],*V2[MAXV];
    int tope=-1;
    inline void addedge(int x,int y)
    {
            E[++tope].np=y;
            E[tope].next=V1[x];
            V1[x]=&E[tope];
    }
    inline void addedge2(int x,int y)
    {
            E[++tope].np=y;
            E[tope].next=V2[x];
            V2[x]=&E[tope];
    }
    int q[MAXV];
    int fa[MAXV];
    int w[MAXV];
    void bfs()
    {
            register int head=-1,tail=0;
            register int now;
            register Edge *ne;
            q[0]=1;
            fa[1]=1;
            while (head<tail)
            {
                    now=q[++head];
                    for (ne=V1[now];ne;ne=ne->next)
                    {
                            if (ne->np==fa[now])continue;
                            fa[ne->np]=now;
                            q[++tail]=ne->np;
                    }
            }
    }
    int bb[MAXV],sb[MAXN],tp[MAXN];
    int root[MAXN];
    int ss;
    int topb=1;
    inline void Add_node(int f,int id,int ww)
    {
            w[id]=ww;
            if (sb[bb[f]]>=ss)
            {
                    bb[id]=++topb;
                    tp[topb]=id;
                    addedge2(bb[f],topb);
            }
            else
                    bb[id]=bb[f];
            sb[bb[id]]++;
            Insert(root[bb[id]],ww);
    }
    inline void Modify_node(int now,int v)
    {
            Erase(root[bb[now]],w[now]);
            w[now]=v;
            Insert(root[bb[now]],w[now]);
    }
    
    int Scan_block(register int now,int kk)
    {
            register int ret=0;
            register Edge *ne;
            ret+=Count_greater(root[now],kk);
            for (ne=V2[now];ne;ne=ne->next)
                    ret+=Scan_block(ne->np,kk);
            return ret;
    }
    int Search_tree(register int now,int kk)
    {
            if (tp[bb[now]]==now)
                    return Scan_block(bb[now],kk);
            else
            {
                    register int ret=w[now]>kk;
                    register Edge *ne;
                    for (ne=V1[now];ne;ne=ne->next)
                            ret+=Search_tree(ne->np,kk);
                    return ret;
            }
    }
    int main()
    {
            //freopen("input.txt","r",stdin);
            //freopen("output.txt","w",stdout);
            int i,x,y,n;
            int m;
            int now;
            n=nextInt();
            for (i=1;i<n;i++)
            {
                    x=nextInt();y=nextInt();
                    addedge(x,y);
                    addedge(y,x);
            }
            for (i=1;i<=n;i++)
                    w[i]=nextInt();
            bfs();
            memset(V1,0,sizeof(V1));
            tope=-1;
            for (i=2;i<=n;i++)addedge(fa[i],i);
            ss=(int)sqrt(n);
            sb[1]=1;bb[1]=1;
            for (i=1;i<n;i++)
            {
                    now=q[i];
                    Add_node(fa[now],now,w[now]);
            }
            m=nextInt();
            int opt=0;
            int lastans=0;
            for (i=0;i<m;i++)
            {
                    opt=nextInt();
                    x=nextInt();y=nextInt();
                    x^=lastans;y^=lastans;
                    if (opt==0)
                    {
                            printf("%d
    ",lastans=Search_tree(x,y));
                    }else if (opt==1)
                    {
                            Modify_node(x,y);
                    }else if (opt==2)
                    {
                            Add_node(x,++n,y);
                            addedge(x,n);
                            fa[n]=x;
                    }
            }
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    java两个栈实现一个队列&&两个队列实现一个栈
    Java HashSet和ArrayList的查找Contains()时间复杂度
    Java KMP算法代码
    利用集合求取字符串里每个字符的个数
    快速失败and安全失败
    Java 巴什博弈(取石子报数问题)
    [知识点][施工中] 1.1 部分IDE介绍
    [知识点] 4.4 动态规划进阶模型——树形/DAG/数位DP
    [知识点] 4.3 动态规划基础模型——区间DP/LIS/LCS
    [课堂小笔记] 数字电子技术
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4223937.html
Copyright © 2011-2022 走看看