• P2633 Count on a tree


    题目描述

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

    输入格式

    第一行两个整数N,M。

    第二行有N个整数,其中第i个整数表示点i的权值。

    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

    最后M行每行两个整数(u,v,k),表示一组询问。

    输出格式

    M行,表示每个询问的答案。

    输入输出样例

    输入 #1
    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
    输出 #1
    2
    8
    9
    105
    7

    说明/提示

    HINT:

    N,M<=100000

    暴力自重。。。

    来源:bzoj2588 Spoj10628.

    本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

    主席树乱搞+lca

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 100010;
    
    int n,m,root[maxn],size,head[maxn],lastans,f[maxn][20],dep[maxn],cnt,rank[maxn];
    
    struct hash{
        int val,id;
    }point[maxn];
    
    struct Tree{
        int ls,rs,sum;
    }tree[maxn*40];
    
    bool cmp(const hash& a,const hash& b){
        return a.val<b.val;
    }
    
    struct edge{
        int v,nex;
    }e[maxn<<1];
    
    void adde(int u,int v){
        e[size].v=v;e[size].nex=head[u];head[u]=size++;
    }
    
    void updata(int &rt,int l,int r,int v){
        tree[++cnt]=tree[rt];
        rt=cnt;
        tree[rt].sum++;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(mid>=v) updata(tree[rt].ls,l,mid,v);
        else updata(tree[rt].rs,mid+1,r,v);
    }
    
    void dfs(int u,int fa){
        root[u]=root[fa];
        updata(root[u],1,n,rank[u]);
        f[u][0]=fa;
        dep[u]=dep[fa]+1;
        for(int i=1;i<=18;i++) f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];~i;i=e[i].nex){
            int v=e[i].v;
            if(v==fa) continue;
            dfs(v,u);
        }
    }
    
    int query(int i,int j,int lca,int lcaf,int l,int r,int k){
        if(l==r) return l;
        int d = tree[tree[i].ls].sum+tree[tree[j].ls].sum-tree[tree[lca].ls].sum-tree[tree[lcaf].ls].sum;
        int mid=(l+r)>>1;
        if(d>=k) return query(tree[i].ls,tree[j].ls,tree[lca].ls,tree[lcaf].ls,l,mid,k);
        else return query(tree[i].rs,tree[j].rs,tree[lca].rs,tree[lcaf].rs,mid+1,r,k-d);
    }
    
    int Lca(int u,int v){
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=18;i>=0;i--) if(dep[f[u][i]]>=dep[v]) u=f[u][i];
        if(u==v) return v;
        for(int i=18;i>=0;i--)if(f[u][i]!=f[v][i]){
            u=f[u][i];v=f[v][i];
        }
        return f[u][0];
    }
    
    int query_(int u,int v,int k){
        int lca=Lca(u,v);
        return point[query(root[u],root[v],root[lca],root[f[lca][0]],1,n,k)].val;
    }
    
    int main(){
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&point[i].val),point[i].id=i;
        sort(point+1,point+1+n,cmp);
        for(int i=1;i<=n;i++) rank[point[i].id]=i;
        for(int i=1;i<n;i++){
            int u,v;scanf("%d%d",&u,&v);
            adde(u,v);adde(v,u);
        }
        dfs(1,0);
        for(int i=1;i<=m;i++){
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            lastans=query_(u^lastans,v,k);
            printf("%d
    ",lastans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    docker run 参数含义
    java——数组队列 ArrayQueue
    java——数组栈 ArrayStack
    java——时间复杂度、动态数组
    java——异常类、异常捕获、finally、异常抛出、自定义异常
    java——变量
    java——虚拟机、线程
    java——内部类
    java——object类
    java——抽象类、接口、二者区别
  • 原文地址:https://www.cnblogs.com/plysc/p/11385417.html
Copyright © 2020-2023  润新知