zoukankan      html  css  js  c++  java
  • [bzoj2588][ Count on a tree]

    题目链接

    思路

    查询区间第k小,考虑主席树。因为是从u到v的简单路径上,考虑将路径分为从u到lca和从lca到v两部分。所以对于每个点都维护出从根节点到当前节点中的点。查询的时候只要用ans[u] + ans[v] - ans[lca] - ans[fa[lca]]就行了。也就是在主席树的查询代码上略加修改。

    代码

    /*
    * @Author: wxyww
    * @Date:   2018-12-11 17:19:03
    * @Last Modified time: 2018-12-11 18:05:14
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<map>
    #include<cmath>
    #include<ctime>
    #include<algorithm>
    #include<bitset>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N = 100000 + 100,logN = 19;
    vector<int>e[N];
    map<int,int>ma;
    ll read() {
       ll x=0,f=1;char c=getchar();
       while(c<'0'||c>'9') {
          if(c=='-') f=-1;
          c=getchar();
       }
       while(c>='0'&&c<='9') {
          x=x*10+c-'0';
          c=getchar();
       }
       return x*f;
    }
    int js,n,tot;
    int w[N],tree[N * 30],ls[N * 30],root[N],rs[N * 30],dy[N];
    int lca[N][logN + 5],dep[N];
    void get_lca(int u,int father) {
       for(int i = 1;i <= logN;++i) 
          lca[u][i] = lca[lca[u][i - 1]][i - 1];
       int k = e[u].size();
       for(int i = 0;i < k;++i) {
          int v = e[u][i];
          if(v == father) continue;
          lca[v][0] = u;
          dep[v] = dep[u] + 1;
          get_lca(v,u);
       }
    }
    int LCA(int x,int y) {
       if(dep[x] < dep[y]) swap(x,y);
       for(int i = logN;i >= 0;--i) if(dep[lca[x][i]] >= dep[y]) x = lca[x][i];
       if(x == y) return x;
       for(int i = logN;i >= 0;--i) if(lca[x][i] != lca[y][i]) x = lca[x][i],y = lca[y][i];
       return lca[x][0];
    }
    void update(int &rt,int lst,int l,int r,int pos) {
       rt = ++tot;
       ls[rt] = ls[lst];rs[rt] = rs[lst];
       tree[rt] = tree[lst] + 1;
       if(l == r) return;
       int mid = (l + r) >> 1;
       if(pos <= mid) update(ls[rt],ls[lst],l,mid,pos);
       else update(rs[rt],rs[lst],mid + 1,r,pos);
    }
    int query(int L,int R,int Lca,int falca,int k,int l,int r) {
       int z = tree[ls[L]] + tree[ls[R]] - tree[ls[Lca]] - tree[ls[falca]];//与普通主席树不同的地方
       if(l == r) return l;
       int mid = (l + r) >> 1;
       if(k <= z) return query(ls[L],ls[R],ls[Lca],ls[falca],k,l,mid);
       else return query(rs[L],rs[R],rs[Lca],rs[falca],k - z,mid + 1,r);
    }
    void dfs(int u,int father) {
       int k = e[u].size();
       update(root[u],root[father],1,js,w[u]);
       for(int i = 0;i < k;++i) {
          int v = e[u][i];
          if(v == father) continue;
          dfs(v,u);
       }
    }
    int main() {
       n = read();int m = read();
       for(int i = 1;i <= n;++i) ls[i] = w[i] = read();
       sort(ls + 1,ls + n + 1);
       ma[ls[1]] = ++js;
       dy[js] = ls[1];
       for(int i = 2; i <= n;++i) if(ls[i] != ls[i - 1]) ma[ls[i]] = ++js,dy[js] = ls[i];
       for(int i = 1;i <= n;++i) w[i] = ma[w[i]];
       for(int i = 1;i < n;++i) {
          int u = read(),v = read();
          e[u].push_back(v);e[v].push_back(u);
       }
       dfs(1,0);
       dep[1] = 1;
       get_lca(1,0);
       int LST = 0;
       while(m--) {
          int l = read() ^ LST,r = read(),k = read();
          int z = LCA(l,r);
          // printf("%d %d %d
    ",l,r,z);
          LST = dy[query(root[l],root[r],root[z],root[lca[z][0]],k,1,js)];
          printf("%d
    ",LST);
       }
       return 0;
    }
    
    
  • 相关阅读:
    java 模拟http请求,通过流(stream)的方式,发送json数据和文件
    $listeners 在vue中的使用 --初学
    vue中关于checkbox数据绑定v-model指令说明
    Vue--理解非prop特性
    Vue里标签嵌套限制问题解决------解析DOM模板时注意事项:
    vue click.stop
    @click.prevent.self和@click.self.prevent区别
    assign()-JS
    摘抄大神对VUE 中slot-scope的深度理解
    oracle11G备份空表解决办法
  • 原文地址:https://www.cnblogs.com/wxyww/p/10104554.html
Copyright © 2011-2022 走看看