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

    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

    暴力自重。。。
     
    思路:
    强制在线,lca + 主席树
     
    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    const int M = 2e5 + 10;
    int p[M][30],dep[M],head[M],sum[M*20],ls[M*20],rs[M*20],root[M*20];
    int cnt1,n,idx,cnt,f[M];
    
    struct node {
        int to,next;
    }e[M];
    
    void add(int u,int v){
        e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;
        e[++cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1;
    }
    
    int lca(int a,int b){
        if(dep[a] > dep[b]) swap(a,b);
        int h = dep[b] - dep[a];
        for(int i = 0;(1<<i)<=h;i++){
            if((1<<i)&h) b = p[b][i];
        }
    
        if(a!=b){
            for(int i = 22;i >= 0;i --){
                if(p[a][i]!=p[b][i]){
                    a = p[a][i]; b = p[b][i];
                }
            }
            a = p[a][0];
        }
        return a;
    }
    
    void build(int l,int r,int &rt){
        rt = ++idx;
        sum[rt] = 0;
        if(l == r) return;
        mid;
        build(l,m,ls[rt]);
        build(m+1,r,rs[rt]);
    }
    
    void update(int p,int l,int r,int old,int &rt){
        rt = ++idx;
        ls[rt] = ls[old]; rs[rt] = rs[old]; sum[rt] = sum[old] + 1;
        if(l == r) return ;
        mid;
        if(p <= m) update(p,l,m,ls[old],ls[rt]);
        else update(p,m+1,r,rs[old],rs[rt]);
    }
    
    int query(int a,int b,int lc,int cl,int l,int r,int k){
        if(l == r) return l;
        mid;
        int cnt = sum[ls[a]] + sum[ls[b]] - sum[ls[lc]] - sum[ls[cl]];
        if(k <= cnt)
            return query(ls[a],ls[b],ls[lc],ls[cl],l,m,k);
        else
            return query(rs[a],rs[b],rs[lc],rs[cl],m+1,r,k-cnt);
    }
    int a[M],b[M];
    
    void dfs(int u,int fa){
        f[u] = fa;
        update(a[u],1,cnt,root[fa],root[u]);
        for(int i = head[u];i;i = e[i].next){
            int v = e[i].to;
            if(v == fa) continue;
            p[v][0] = u;
            dep[v] = dep[u] + 1;
            dfs(v,u);
        }
    }
    
    void init()
    {
        cnt1 = 0; idx = 0;
        memset(head,0,sizeof(head));
        memset(dep,0,sizeof(dep));
        memset(p,0,sizeof(p));
        memset(f,0,sizeof(f));
        dep[1] = 1;
    }
    
    int main()
    {
        int m;
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            for(int i = 1; i <= n;i ++){
                scanf("%d",&a[i]);
                b[i] = a[i];
            }
            int l,r,c;
            sort(b+1,b+n+1);
            cnt = unique(b+1,b+1+n)-b-1;
            for(int i = 1;i <= n;i ++)
                a[i] = lower_bound(b+1,b+cnt+1,a[i]) - b;
            for(int i = 1;i <= n-1;i ++){
                scanf("%d%d",&l,&r);
                add(l,r);
            }
            build(1,cnt,root[0]);
            dfs(1,0);
            for(int j = 1;(1<<j)<=n;j++)
                for(int i = 1;i <= n;i++)
                    p[i][j] = p[p[i][j-1]][j-1];
            int num = 0;
            for(int i = 1;i <= m;i ++){
                scanf("%d%d%d",&l,&r,&c);
                l = l^num;
                int lc = lca(l,r);
                int id = query(root[l],root[r],root[lc],root[f[lc]],1,cnt,c);
                num = b[id];
                printf("%d
    ",b[id]);
            }
        }
        return 0;
    }
  • 相关阅读:
    [转] CSocket 和CAsyncSocket类介绍
    error C2275: 'SOCKET' : illegal use of this type as an expression
    tagVARIANT、VARIANT、_variant_t和COleVariant
    使用MFC WinInet进行FTP中文件的简单上传和下载功能
    【转】VS2008快速将代码中字符串改为_T(“”)风格的方法
    【转】Internet与Intranet区别
    POSIX是什么?
    Ocx控件注册不成功?可能是tlb文件导致~
    十三种基于直方图的图像全局二值化算法原理、实现、代码及效果(转)
    图像匹配之欧式距离算法(转)
  • 原文地址:https://www.cnblogs.com/kls123/p/9930742.html
Copyright © 2011-2022 走看看