• 【BZOJ-2588】Count on a tree 主席树 + 倍增


    2588: Spoj 10628. Count on a tree

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

    Solution

    区间第k小?必然是主席树

    树上第k小?显然把主席树建在树上即可,亦或把主席树建在DFS序上

    那么考虑把主席树建在树上,仍旧需要DFS序,还需要预处理出LCA,对建树和询问做一些修改即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define maxn 100010
    int n,m;int val[maxn];int ls[maxn],num;
    struct data{int to,next;}edge[maxn<<1];
    int head[maxn],cnt;
    void add(int u,int v){cnt++;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;}
    void insert(int u,int v){add(u,v);add(v,u);}
    int steck[maxn],top,father[maxn][25],deep[maxn],pos[maxn];
    void dfs(int x)
    {
        steck[++top]=x; pos[x]=top;
        for (int i=1; i<=20; i++)
            if (deep[x]>=(1<<i))
                father[x][i]=father[father[x][i-1]][i-1];
            else break;
        for (int i=head[x]; i; i=edge[i].next)
            if (father[x][0]!=edge[i].to) 
                father[edge[i].to][0]=x,deep[edge[i].to]=deep[x]+1,dfs(edge[i].to); 
    }
    int LCA(int x,int y)
    {
        if (deep[x]<deep[y]) swap(x,y);
        int dd=deep[x]-deep[y];
        for (int i=0; i<=20; i++)
            if (dd&(1<<i)) x=father[x][i];
        for (int i=20; i>=0; i--)
            if (father[x][i]!=father[y][i])
                x=father[x][i],y=father[y][i];
        if (x==y) return x; else return father[x][0];
    }
    int sum[maxn*20],ll[maxn*20],rr[maxn*20],root[maxn<<2],sz; 
    void update(int l,int r,int &now,int fat,int va) 
    { 
        now=++sz; sum[now]=sum[fat]+1; 
        if (l==r) return; 
        ll[now]=ll[fat],rr[now]=rr[fat]; 
        int mid=(l+r)>>1; 
        if (va<=mid) update(l,mid,ll[now],ll[fat],va); 
        else update(mid+1,r,rr[now],rr[fat],va); 
    } 
    int query(int l,int r,int L,int R,int k) 
    { 
        int lca=LCA(L,R),fa=father[lca][0];
        int a=root[pos[L]],b=root[pos[R]],c=root[pos[lca]],d=root[pos[fa]];
        while (l<r)
            {
                int mid=(l+r)>>1;
                int summ=sum[ll[a]]+sum[ll[b]]-sum[ll[c]]-sum[ll[d]];
                if (summ>=k) r=mid,a=ll[a],b=ll[b],c=ll[c],d=ll[d];
                    else k-=summ,l=mid+1,a=rr[a],b=rr[b],c=rr[c],d=rr[d]; 
            }
        return l;
    }
    int main()
    {
        n=read(),m=read();
        for (int i=1; i<=n; i++) val[i]=read(),ls[i]=val[i];
        sort(ls+1,ls+n+1);
        for (int i=1; i<=n; i++) if (ls[i]!=ls[i-1]) ls[++num]=ls[i];
        for (int i=1; i<=n; i++) val[i]=lower_bound(ls+1,ls+num+1,val[i])-ls; 
        for (int u,v,i=1; i<=n-1; i++)
            u=read(),v=read(),insert(u,v);
        dfs(1);
        for (int tmp,i=1; i<=n; i++)
            tmp=steck[i],update(1,num,root[i],root[pos[father[tmp][0]]],val[tmp]);
        int lastans=0,ans=0;
        for (int u,v,k,i=1; i<=m; i++)
            {
                u=read(),v=read(),k=read(); u^=lastans;
                ans=query(1,num,u,v,k); ans=ls[ans];
                printf("%d",ans); if (i!=m) puts("");
                lastans=ans; 
            }
        return 0;
    } 

    你丫这题卡最后一行的行末换行...强行PE...好像切题又被蛋蛋发现了...

  • 相关阅读:
    Docker 简单部署 ElasticSearch
    Anaconda更新失败简单解决[CondaHTTPError: HTTP 000 CONNECTION FAILED for url]
    TermKit的新一代Mac终端,在Ubuntu 11.04 轻松安装TermKit
    Linux下如何测试网速
    centos7安装yum
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    yum 安装指定版本Docker
    如何在 Apache Hive 中解析 Json 数组
    unzip解压失败( cannot find zipfile directory)
    Linux 定时任务crontab_014
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5348642.html
Copyright © 2020-2023  润新知