• [bzoj2588][Spoj10628]Count on a tree_主席树


    Count on a tree bzoj-2588 Spoj-10628

    题目大意:给定一棵n个点的树,m次查询。查询路径上k小值。

    注释:$1le n,mle 10^5$。

    想法:好像更博顺序有一些问题... ...

    root[i]表示以i为根的主席树根

    对于查询的两个点x,y,我们只需要查询

    root[x]+root[y]-root[lca(x,y)]-root[fa[lca(x,y)]]的主席树即可。

    具体地,每个节点的权值线段树维护的是当前结点到根的路径上这些点权值的权值线段树。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    using namespace std;
    int ans,tot,cnt,anc,n,m,q,x,y,z,d[100010],v[100010],h[100010],l[3000010],r[3000010],to[200010],head[100010],next[200010],sum[3000010],root[100010],f[100010][20];
    map<int,int>b;
    void add(int x,int y)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
    }
    int lca(int x,int y)
    {
        if(d[x]<d[y])
        {
            swap(x,y);
        }
        int dep=d[x]-d[y];
        for(int i=0;i<=19;i++)
        {
            if((dep&(1<<i))!=0)
            {
                x=f[x][i];
            }
        }
        if(x==y)
        {
            return x;
        }
        for(int i=19;i>=0;i--)
        {
            if(f[x][i]!=f[y][i])
            {
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];
    }
    int updata(int pre,int L,int R,int k)
    {
    	int mid=(L+R)>>1;
        int rt=++cnt;
        l[rt]=l[pre];
        r[rt]=r[pre];
        sum[rt]=sum[pre]+1;
        if(L==R)
        {
            return rt;
        }
        else
        {
            if(k<=mid)
            {
                l[rt]=updata(l[pre],L,mid,k);
            }
            else
            {
                r[rt]=updata(r[pre],mid+1,R,k);
            }
        }
        return rt;
    }
    int query(int x,int y,int anc,int fa,int L,int R,int k)
    {
    	int mid=(L+R)>>1;
        if(L==R)
        {
            return b[L];
        }
        int num=sum[l[x]]+sum[l[y]]-sum[l[anc]]-sum[l[fa]];
        if(num>=k)
        {
            return query(l[x],l[y],l[anc],l[fa],L,mid,k);
        }
        else
        {
            return query(r[x],r[y],r[anc],r[fa],mid+1,R,k-num);
        }
    }
    void dfs(int x,int fa)
    {
        d[x]=d[fa]+1;
        int k=lower_bound(h+1,h+1+m,v[x])-h;
        b[k]=v[x];
        root[x]=updata(root[fa],1,n,k);
        for(int i=1;i<=19;i++)
        {
            f[x][i]=f[f[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=next[i])
        {
            if(to[i]!=fa)
            {
                f[to[i]][0]=x;
                dfs(to[i],x);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
            h[i]=v[i];
        }
        sort(h+1,h+1+n);
        m=unique(h+1,h+1+n)-h-1;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            x=x^ans;
            anc=lca(x,y);
            ans=query(root[x],root[y],root[anc],root[f[anc][0]],1,n,z);
            printf("%d
    ",ans);
        }
    }
    

    小结:在树上的主席树就是nb... ...

  • 相关阅读:
    python全栈开发day76-博客主页
    python全栈开发day75-用户注册页面ajax实现,用户头像上传、预览、展示
    python全栈开发day74-普通验证码和滑块验证码
    python全栈开发day73-Django认证系统
    python全栈开发day72-django之Form组件
    python全栈开发day70-Django中间件
    python全栈开发day69-cookie、session
    python全栈开发day68-ORM操作:一般操作、ForeignKey操作、ManyToManyField、聚合查询和分组查询、F查询和Q查询等
    选择排序
    冒泡排序
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9362809.html
Copyright © 2020-2023  润新知