zoukankan      html  css  js  c++  java
  • BZOJ2588:LCA+主席树来实现树上两点之间第K大点权查询

    对于每个节点维护这个节点到根的权值线段树

    对于每个询问(x,y),这条路径上的线段树

    tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]]

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 const int maxn=100005;
      5 const int maxm=2000005;
      6 int n,m,tot,cnt,ind,sz,last;
      7 int tmp[maxn],hash[maxn],g[maxn],v[maxn];
      8 int num[maxn],pos[maxn],deep[maxn];
      9 int sum[maxm],lch[maxm],rch[maxm];
     10 int root[maxn];
     11 int fa[maxn][17];
     12 struct Edge
     13 {
     14     int t,next;
     15 }e[2*maxn];
     16 inline long long read()
     17 {
     18     long long x=0,f=1;char ch=getchar();
     19     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     20     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     21     return x*f;
     22 }
     23 //二分查找离散化之后的x的下标 
     24 int find(int x)
     25 {
     26     int l=1,r=tot;
     27     while(l<=r)
     28     {
     29         int mid=(l+r)>>1;
     30         if(hash[mid]<x) l=mid+1;
     31         else if(hash[mid]==x) return mid;
     32         else r=mid-1;
     33     }
     34     return l;
     35 }
     36 void insert(int u,int v)
     37 {
     38     cnt++;
     39     e[cnt].t=v;e[cnt].next=g[u];g[u]=cnt;
     40     cnt++;
     41     e[cnt].t=u;e[cnt].next=g[v];g[v]=cnt;
     42 }
     43 void dfs(int x)
     44 {
     45     ind++;num[ind]=x;pos[x]=ind;
     46     for(int i=1;i<=16;i++)
     47         if((1<<i)<=deep[x]) fa[x][i]=fa[fa[x][i-1]][i-1];
     48         else break;
     49     for(int tmp=g[x];tmp;tmp=e[tmp].next)
     50     {
     51         if(fa[x][0]!=e[tmp].t)
     52         {
     53             deep[e[tmp].t]=deep[x]+1;
     54             fa[e[tmp].t][0]=x;
     55             dfs(e[tmp].t);
     56         }
     57     }
     58 }
     59 void update(int l,int r,int x,int &y,int num)
     60 {
     61     y=++sz;
     62     sum[y]=sum[x]+1;
     63     if(l==r) return;
     64     lch[y]=lch[x];rch[y]=rch[x];
     65     int mid=(l+r)>>1;
     66     if(num<=mid)
     67         update(l,mid,lch[x],lch[y],num);
     68     else update(mid+1,r,rch[x],rch[y],num);
     69 } 
     70 int lca(int x,int y)
     71 {
     72     if(deep[x]<deep[y]) swap(x,y);
     73     int t=deep[x]-deep[y];
     74     for(int i=0;i<=16;i++)
     75         if((1<<i)&t) x=fa[x][i];
     76     for(int i=16;i>=0;i--)
     77         if(fa[x][i]!=fa[y][i])
     78             x=fa[x][i],y=fa[y][i];
     79     if(x==y) return x;
     80     return fa[x][0];
     81 }
     82 int query(int x,int y,int rk)
     83 {
     84     int a=x,b=y,c=lca(x,y),d=fa[c][0];
     85     a=root[pos[a]],b=root[pos[b]],c=root[pos[c]],d=root[pos[d]];
     86     int l=1,r=tot;
     87     while(l<r)
     88     {
     89         int mid=(l+r)>>1;
     90         int tmp=sum[lch[a]]+sum[lch[b]]-sum[lch[c]]-sum[lch[d]];
     91         if(tmp>=rk) r=mid,a=lch[a],b=lch[b],c=lch[c],d=lch[d];
     92         else rk-=tmp,l=mid+1,a=rch[a],b=rch[b],c=rch[c],d=rch[d];
     93     }
     94     return hash[l];
     95 }
     96 int main()
     97 {
     98     n=read();m=read();
     99     for(int i=1;i<=n;i++)
    100         v[i]=read(),tmp[i]=v[i];
    101     sort(tmp+1,tmp+n+1);  //点权排序
    102     hash[++tot]=tmp[1];
    103     for(int i=2;i<=n;i++)
    104         if(tmp[i]!=tmp[i-1])
    105             hash[++tot]=tmp[i];
    106     //离散化 
    107     for(int i=1;i<=n;i++) v[i]=find(v[i]); 
    108     //存位置,离散化
    109     for(int i=1;i<n;i++)
    110     {
    111         int u,v;
    112         u=read();v=read();
    113         insert(u,v);
    114     } 
    115     dfs(1);
    116     for(int i=1;i<=n;i++)
    117     {
    118         int t=num[i];  //树上点权
    119         update(1,tot,root[pos[fa[t][0]]],root[i],v[t]);//建立主席树 
    120     }
    121     for(int i=1;i<=m;i++)
    122     {
    123         int x=read(),y=read(),rk=read();
    124         x^=last;
    125         last=query(x,y,rk);
    126         printf("%d",last);
    127         if(i!=m) printf("
    ");
    128     }
    129     return 0;
    130 }
  • 相关阅读:
    make_blobs(源码)
    odoo13
    Odoo Community & Enterprise | & 我的一些瞎扯。。
    odoo 应用笔记 01 [草稿]
    PVE 为虚拟机 直通硬盘
    freebsd 断电 单用户模式恢复
    odoo 绿色版
    WSL 手动下载安装
    Command pg_dump not found
    odoo性能优化
  • 原文地址:https://www.cnblogs.com/aininot260/p/9599987.html
Copyright © 2011-2022 走看看