zoukankan      html  css  js  c++  java
  • BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree

    Time Limit: 12 Sec  Memory Limit: 128 MB
    Submit: 5217  Solved: 1233
    [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

    每个节点建一棵主席树,维护树上前缀和
    每次u和v之间的就是ls(u)+ls(v)-ls(lca(u,v))-ls(fa[lca(u,v)])
    很多人用了dfs序的编号,没有必要
     
    注意:
    1.数组空间!!!!
    2.lca用树剖的话,建树时dfs的顺序也要先重链!!!!!
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,INF=1e9+5;
    int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,Q,u,v,k,last,mp[N],m,w[N];
    struct ques{
        int u,v,k;
    }q[N];
    int Bin(int v){
        int l=1,r=m;
        while(l<=r){
            int mid=(l+r)>>1;
            if(mp[mid]==v) return mid;
            else if(v<mp[mid]) r=mid-1;
            else l=mid+1;
        }
        return -1;
    }
    struct edge{
        int v,ne;
    }e[N<<1];
    int h[N],cnt;
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int size[N],fa[N],deep[N],mx[N],top[N],tid[N],tot;
    void dfs(int u){
        size[u]=1;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u]) continue;
            fa[v]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[mx[u]]<size[v]) mx[u]=v;
        }
    }
    void dfs(int u,int anc){
        if(!u) return;
        tid[u]=++tot;
        top[u]=anc;
        dfs(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
        }
    }
    int lca(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        return x;
    }
    
    struct node{
        int l,r,size;
    }t[N*20];
    int sz,root[N];
    void insert(int &x,int l,int r,int num){
        t[++sz]=t[x];x=sz;
        t[x].size++;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(num<=mid) insert(t[x].l,l,mid,num);
        else insert(t[x].r,mid+1,r,num);
    }
    void build(int u){
        root[u]=root[fa[u]];
        insert(root[u],1,m,Bin(w[u]));
        if(mx[u]) build(mx[u]);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa[u]&&e[i].v!=mx[u]) build(e[i].v);
    }
    inline int ls(int x){return t[t[x].l].size;}
    int query(int u,int v,int k){
        int p=lca(u,v),q=fa[p];
        u=root[u];v=root[v];p=root[p];q=root[q];
        int l=1,r=m;
        while(l!=r){
            int mid=(l+r)>>1,_=ls(u)+ls(v)-ls(p)-ls(q);
            if(k<=_) r=mid,u=t[u].l,v=t[v].l,p=t[p].l,q=t[q].l;
            else l=mid+1,u=t[u].r,v=t[v].r,p=t[p].r,q=t[q].r,k-=_; 
        }
        return l;
    }
    int main(){
        n=read();Q=read();
        for(int i=1;i<=n;i++) mp[i]=w[i]=read();
        for(int i=1;i<=n-1;i++) u=read(),v=read(),ins(u,v);
        dfs(1);dfs(1,1);
        for(int i=1;i<=Q;i++) q[i].u=read(),q[i].v=read(),q[i].k=read();
        sort(mp+1,mp+1+n);
        m=1;
        for(int i=2;i<=n;i++) if(mp[i]!=mp[i-1]) mp[++m]=mp[i];
        
        build(1);
        for(int i=1;i<=Q;i++){
            u=last^q[i].u;v=q[i].v;k=q[i].k;
            last=mp[query(u,v,k)];
            printf("%d",last);
            if(i!=Q) putchar('
    ');
        }
    }
     
     
  • 相关阅读:
    实验二 递归下降语法分析
    作业十一
    第七次作业逻辑回归实践
    机器学习第六次作业
    第五次作业
    第三次作业k均值算法
    第二次作业
    机器学习作业一
    14次作业
    12 实验二 递归下降语法分析
  • 原文地址:https://www.cnblogs.com/candy99/p/6218505.html
Copyright © 2011-2022 走看看