zoukankan      html  css  js  c++  java
  • bzoj 2588: Spoj 10628. Count on a tree LCA+主席树

    2588: Spoj 10628. Count on a tree

    Time Limit: 12 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    Description

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
     

    Input

    第一行两个整数N,M。
    第二行有N个整数,其中第i个整数表示点i的权值。
    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
    最后M行每行两个整数(u,v,k),表示一组询问。
     

    Output

    M行,表示每个询问的答案。最后一个询问不输出换行符

    Sample Input

    8 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2

    Sample Output

    2
    8
    9
    105
    7

    HINT




    HINT:

    N,M<=100000

    暴力自重。。。

    Source

    鸣谢seter

    dfs序,然后求LCA;

    分成两条链求第K小;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e5+30010,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
    struct Chairmantree
    {
        int rt[N*20],ls[N*20],rs[N*20],sum[N*20];
        int tot;
        void init()
        {
            tot=0;
        }
        void build(int l,int r,int &pos)
        {
            pos=++tot;
            sum[pos]=0;
            if(l==r)return;
            int mid=(l+r)>>1;
            build(l,mid,ls[pos]);
            build(mid+1,r,rs[pos]);
        }
        void update(int p,int c,int pre,int l,int r,int &pos)
        {
            pos=++tot;
            ls[pos]=ls[pre];
            rs[pos]=rs[pre];
            sum[pos]=sum[pre]+c;
            if(l==r)return;
            int mid=(l+r)>>1;
            if(p<=mid)
                update(p,c,ls[pre],l,mid,ls[pos]);
            else
                update(p,c,rs[pre],mid+1,r,rs[pos]);
        }
        int rank(int s,int e,int L,int R,int l,int r)
        {
            if(L<=l&&r<=R)return sum[e]-sum[s];
            int mid=(l+r)>>1;
            int ans=0;
            if(L<=mid)
                ans+=rank(ls[s],ls[e],L,R,l,mid);
            if(R>mid)
                ans+=rank(rs[s],rs[e],L,R,mid+1,r);
            return ans;
        }
        int query(int L,int R,int S,int T,int l,int r,int k)
        {
            if(l==r)return l;
            int mid=(l+r)>>1;
            int x=sum[ls[R]]-sum[ls[L]]+sum[ls[T]]-sum[ls[S]];
            if(k<=x) return query(ls[L],ls[R],ls[S],ls[T],l,mid,k);
            else return query(rs[L],rs[R],rs[S],rs[T],mid+1,r,k-x);
        }
    };
    Chairmantree tree;
    struct edge
    {
        int v,next;
    }edge[N<<1];
    int head[N],fa[N][30],edg,deep[N];
    int in[N],out[N],tot,flag[N];
    void init()
    {
        memset(in,0,sizeof(in));
        memset(deep,0,sizeof(deep));
        memset(head,-1,sizeof(head));
        edg=0;
        tot=0;
    }
    void add(int u,int v)
    {
        edg++;
        edge[edg].v=v;
        edge[edg].next=head[u];
        head[u]=edg;
    }
    void dfs(int u,int fat)
    {
        tot++;
        in[u]=tot;
        for (int i=1; i<=18 ;i++) {
            if(deep[u]<(1<<i)) break;
            fa[u][i] = fa[fa[u][i-1]][i-1];
        }
        for (int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==fat) continue;
            deep[v]=deep[u]+1;
            fa[v][0]=u;
            dfs(v,u);
        }
        out[u]=tot;
    }
    int RMQ_LCA(int x,int y) {
        if(deep[x]<deep[y]) swap(x,y);
        int d=deep[x]-deep[y];
        for (int i=0; i<=18 ;i++)
            if((1<<i)&d) x=fa[x][i];
        for (int i=18; i>=0 ;i--) {
            if(fa[x][i]!=fa[y][i]) {
                x=fa[x][i];y=fa[y][i];
            }
        }
        if(x==y) return x;
        else return fa[x][0];
    }
    int a[N],b[N];
    int getpos(int x,int n)
    {
        int p=lower_bound(b+1,b+1+n,x)-b;
        return p;
    }
    int main()
    {
        int n,m;
        int le=1e5+10;
        while(~scanf("%d%d",&n,&m))
        {
            init();
            tree.init();
            tree.build(1,le,tree.rt[0]);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]),b[i]=a[i];
            sort(b+1,b+1+n);
            for(int i=1;i<n;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }
            dfs(1,0);
            for(int i=1;i<=n;i++)
                flag[in[i]]=i;
            for(int i=1;i<=n;i++)
            {
                int p=getpos(a[flag[i]],n);
                //cout<<p<<" "<<in[fa[flag[i]][0]]<<endl;
                tree.update(p,1,tree.rt[in[fa[flag[i]][0]]],1,le,tree.rt[i]);
            }
            int ans=0;
            while(m--)
            {
                int u,v,k;
                scanf("%d%d%d",&u,&v,&k);
                u^=ans;
                int w=RMQ_LCA(u,v);
                ans=b[tree.query(tree.rt[in[w]],tree.rt[in[v]],tree.rt[in[fa[w][0]]],tree.rt[in[u]],1,le,k)];
                printf("%d",ans);
                if(m)
                    printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    受约束的十人参赛问题
    受约束的10人参赛问题
    [转载]A、B、C、D、E、F、G、H、I、J 共10名学生有可能参加本次计算机竞
    使用SSH集成框架开发项目步骤
    Java语言高职组最后一题题
    受约束的十人参赛问题
    setsockopt的TCP层实现剖析
    周鸿祎:做产品体验先把自己切换到二傻子模式
    sysctl使用方法的变化
    产品设计核心要做到极致
  • 原文地址:https://www.cnblogs.com/jhz033/p/6523194.html
Copyright © 2011-2022 走看看