zoukankan      html  css  js  c++  java
  • 主席树初探--BZOJ2588: Spoj 10628. Count on a tree

    n<=100000的点权树,有m<=100000个询问,每次问两个点间的第k小点权,保证有解,强制在线。

    主席上树啦!类似于之前的序列不带修改询问的前缀表示法,现在只要把前缀当成某点到根的信息即可。然后比如要问x点和y点,z为lca(x,y),w为z的爸爸,那么x,y,z,w四棵线段树一起跑即可。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<stdlib.h>
      5 //#include<iostream>
      6 using namespace std;
      7 
      8 int n,m;
      9 #define maxn 100011
     10 #define maxm 2000011
     11 struct SMT
     12 {
     13     struct Node
     14     {
     15         int son[2];
     16         int cnt;
     17     }a[maxm];
     18     int size,n;
     19     void clear(int m) {n=m;size=0;a[0].cnt=0;}
     20     void build(int pre,int &rt,int L,int R,int num)
     21     {
     22         rt=++size;
     23         a[rt].cnt=a[pre].cnt+1;
     24         if (L==R) {a[rt].son[0]=a[rt].son[1]=0;return;}
     25         const int mid=(L+R)>>1;
     26         if (num<=mid) build(a[pre].son[0],a[rt].son[0],L,mid,num),a[rt].son[1]=a[pre].son[1];
     27         else build(a[pre].son[1],a[rt].son[1],mid+1,R,num),a[rt].son[0]=a[pre].son[0];
     28     }
     29     void build(int pre,int &rt,int num) {build(pre,rt,1,n,num);}
     30 //    void test(int x,int L,int R)
     31 //    {
     32 //        const int mid=(L+R)>>1;
     33 //        if (a[x].son[0]) test(a[x].son[0],L,mid);
     34 ////        cout<<L<<' '<<R<<' '<<a[x].cnt<<endl;
     35 //        if (a[x].son[1]) test(a[x].son[1],mid+1,R);
     36 //    }
     37 //    void test(int x) {test(x,1,n);}
     38 }smt;
     39 
     40 struct Edge{int to,next;}edge[maxn<<1];int first[maxn],le=2;
     41 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
     42 void insert(int x,int y) {in(x,y);in(y,x);}
     43 
     44 int a[maxn],b[maxn],lb;
     45 int fa[maxn][22],dep[maxn],rt[maxn];
     46 void dfs(int x,int f)
     47 {
     48     fa[x][0]=f;dep[x]=dep[f]+1;
     49     for (int j=1;j<=18;j++)
     50         fa[x][j]=fa[fa[x][j-1]][j-1];
     51     smt.build(rt[f],rt[x],a[x]);
     52     for (int i=first[x];i;i=edge[i].next)
     53     {
     54         const Edge &e=edge[i];if (e.to==f) continue;
     55         dfs(e.to,x);
     56     }
     57 }
     58 void pre() {dfs(1,0);}
     59 
     60 int lca(int x,int y)
     61 {
     62     if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
     63     for (int i=18;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
     64     if (x==y) return x;
     65     for (int i=18;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
     66     return fa[x][0];
     67 }
     68 
     69 int main()
     70 {
     71     scanf("%d%d",&n,&m);
     72     for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
     73     lb=n;sort(b+1,b+1+lb);lb=unique(b+1,b+1+lb)-b-1;
     74     for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+lb,a[i])-b;
     75     
     76     smt.clear(lb);
     77     for (int i=1,x,y;i<n;i++)
     78     {
     79         scanf("%d%d",&x,&y);
     80         insert(x,y);
     81     }
     82     pre();
     83 //    for (int i=1;i<=n;i++) smt.test(rt[i]),cout<<endl;
     84     int last=0;
     85     for (int i=1,x,y,K;i<=m;i++)
     86     {
     87         scanf("%d%d%d",&x,&y,&K);
     88         x^=last;
     89         int z=lca(x,y),w=fa[z][0],L=1,R=lb,tmp;
     90 //        cout<<x<<' '<<y<<' '<<z<<' '<<w<<endl;
     91         x=rt[x];y=rt[y];z=rt[z];w=rt[w];
     92         while (L<R)
     93         {
     94             if ((tmp=smt.a[smt.a[x].son[0]].cnt+smt.a[smt.a[y].son[0]].cnt
     95             -smt.a[smt.a[z].son[0]].cnt-smt.a[smt.a[w].son[0]].cnt)>=K)
     96                 x=smt.a[x].son[0],y=smt.a[y].son[0],z=smt.a[z].son[0],w=smt.a[w].son[0],R=(L+R)>>1;
     97             else x=smt.a[x].son[1],y=smt.a[y].son[1],z=smt.a[z].son[1],w=smt.a[w].son[1],K-=tmp,L=((L+R)>>1)+1;
     98 //            cout<<tmp<<' '<<K<<endl;
     99         }
    100         printf("%d",(last=b[L]));
    101         if (i<m) puts("");
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    微信小程序设置控件权重
    从外部浏览开启app
    对rxandroid的简单理解
    react native TextInput
    使用广播来进行刷新页面
    react native中对props和state的理解
    android中四大组件之间相互通信
    android tab选项卡的使用
    android控件 ToggleButton的应用
    Listview的使用
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7927088.html
Copyright © 2011-2022 走看看