[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
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 100000 + 100,logN = 19;
vectore[N];
mapma;
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\n",l,r,z);
      LST = dy[query(root[l],root[r],root[z],root[lca[z][0]],k,1,js)];
      printf("%d\n",LST);
   }
   return 0;
}

你可能感兴趣的:([bzoj2588][ Count on a tree])