zoukankan      html  css  js  c++  java
  • 【树上主席树】BZOJ2588-Count on a tree

    【题目大意】

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
     
    【思路】
    这道题迷之好写,因为思路条理太清晰了!
    我们每个点就是一棵线段树,维护它到根的每个数字的个数,但是这样会MLE所以自然而然地用主席树来维护。
    u->v路径上每种的个数就等于sum[u]-sum[lca(u,v)]+sum[v]-sum[fa[lca(u,v)]]。
    写起来特别爽。
    然而我RE了一个上午。接着突然发现题意“(u,v)表示u到v有一条边)它居然是无向的??天真地以为有向u->v,调出了一开始的程序,默默地改掉,默默地AC...
    还我两小时的人生!!!!
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define lson l,m
      7 #define rson m+1,r
      8 using namespace std;
      9 const int MAXN=100000+500;
     10 const int DEG=20;
     11 int w[MAXN];
     12 vector<int> E[MAXN];
     13 int d,hash[MAXN];
     14 int T[MAXN],tot,sum[MAXN<<5],L[MAXN<<5],R[MAXN<<5];
     15 int anc[MAXN][DEG],dep[MAXN];
     16 int n,m;
     17 
     18 /*Chairman Tree*/
     19 int build(int l,int r)
     20 {
     21     int rt=++tot;
     22     sum[rt]=0;
     23     if (l!=r)
     24     {
     25         int m=(l+r)>>1;
     26         L[rt]=build(lson);
     27         R[rt]=build(rson); 
     28     }
     29     return rt;
     30 }
     31 
     32 int update(int pre,int l,int r,int x)
     33 {
     34     int rt=++tot;
     35     L[rt]=L[pre],R[rt]=R[pre];
     36     sum[rt]=sum[pre]+1;
     37     if (l!=r)
     38     {
     39         int m=(l+r)>>1;
     40         if (x<=m) L[rt]=update(L[pre],lson,x);
     41             else R[rt]=update(R[pre],rson,x);
     42     }
     43     return rt;
     44 }
     45 
     46 int query(int u,int v,int lca,int lcafa,int l,int r,int k)
     47 {
     48     if (l==r) return l;
     49     int num=(sum[L[u]]-sum[L[lca]]+sum[L[v]]-sum[L[lcafa]]);
     50     int m=(l+r)>>1;
     51     if (num>=k) return query(L[u],L[v],L[lca],L[lcafa],lson,k);
     52         else return query(R[u],R[v],R[lca],R[lcafa],rson,k-num);
     53 }
     54 
     55 /*LCA*/
     56 void getanc()
     57 {
     58     for (int i=1;i<DEG;i++)
     59         for (int j=1;j<=n;j++)
     60             anc[j][i]=anc[anc[j][i-1]][i-1];
     61 }
     62 
     63 int swim(int x,int H)
     64 {
     65     for (int i=0;H>0;i++)
     66     {
     67         if (H&1) x=anc[x][i];
     68         H>>=1;
     69     }
     70     return x;
     71 }
     72 
     73 int LCA(int u,int v)
     74 {
     75     if (dep[u]<dep[v]) swap(u,v);
     76     u=swim(u,dep[u]-dep[v]);
     77     if (u==v) return u;
     78     for (int i=DEG-1;i>=0;i--)
     79     {
     80         if (anc[u][i]!=anc[v][i])
     81         {
     82             u=anc[u][i];
     83             v=anc[v][i];
     84         }
     85     }
     86     return anc[u][0];
     87 }
     88  
     89 /*main*/
     90 void dfs(int u,int pa,int depth)
     91 { 
     92     anc[u][0]=pa;
     93     dep[u]=depth;
     94     int x=lower_bound(hash+1,hash+d+1,w[u])-hash;
     95     T[u]=update(T[pa],1,d,x);
     96     for (int i=0;i<E[u].size();i++)
     97         if (E[u][i]!=pa) dfs(E[u][i],u,depth+1);
     98 }
     99 
    100 void init()
    101 {
    102     scanf("%d%d",&n,&m);
    103     for (int i=1;i<=n;i++) scanf("%d",&w[i]),hash[i]=w[i];
    104     sort(hash+1,hash+n+1);
    105     d=unique(hash+1,hash+n+1)-(hash+1);
    106     
    107     for (int i=1;i<n;i++)
    108     {
    109         int u,v;
    110         scanf("%d%d",&u,&v);
    111         E[u].push_back(v);
    112         E[v].push_back(u);
    113     }
    114 
    115     
    116     tot=0;
    117     T[1]=build(1,d);//对于根先建立主席树
    118 }
    119 
    120 void solve()
    121 {
    122     getanc();
    123     int preans=0;
    124     for (int i=0;i<m;i++)
    125     {
    126         int u,v,k;
    127         scanf("%d%d%d",&u,&v,&k);
    128         u=u^preans;
    129         int lca=LCA(u,v);
    130         int ans=query(T[u],T[v],T[lca],T[anc[lca][0]],1,d,k);
    131         printf("%d",hash[ans]);
    132         if (i!=m-1) printf("
    ");
    133         preans=hash[ans];
    134     }
    135 }
    136 
    137 int main()
    138 {
    139     init();
    140     dfs(1,0,1);
    141     solve();
    142     return 0;
    143 }
  • 相关阅读:
    死磕 java线程系列之线程池深入解析——定时任务执行流程
    死磕 java线程系列之线程池深入解析——未来任务执行流程
    死磕 java线程系列之线程池深入解析——普通任务执行流程
    面试 LockSupport.park()会释放锁资源吗?
    死磕 java线程系列之线程池深入解析——生命周期
    死磕 java线程系列之线程的生命周期
    《动手学深度学习》系列笔记—— 1.2 Softmax回归与分类模型
    《动手学深度学习》系列笔记——1.1 线性回归
    【Python学习笔记】2. 高级变量类型
    【Python学习笔记】1. Python基础知识
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5772479.html
Copyright © 2011-2022 走看看