spoj cot Count on a tree

来源:互联网 发布:c 游戏编程 百度网盘 编辑:程序博客网 时间:2024/05/28 17:05
树上k大值 , 主席树模板题
#include <cstdio>#include <algorithm>#include <iostream>#include <cmath>#include <cstring>using namespace std;int const M = 200010;struct edge { int  v,next;   }edge[M*2];int num_edge,num_tree,top ,head[M] , father[M*5];int w[M],lisan[M],len,cnt;void init(){ memset(head,-1,sizeof(head)); num_edge = 0; len  = 0; top=0; cnt =0;}void add(int u,int v) {    edge[num_edge].v = v;    edge[num_edge].next = head[u];    head[u] = num_edge++;}void init_hash() { sort(lisan+1,lisan+1+len); len = unique(lisan+1,lisan+1+len) - 1 - lisan;}int gethash(int o) { return lower_bound(lisan+1,lisan+1+len,o) - lisan;}int dp[M][33],first[M],seq[M],F[M],root[M*40];int insert (int rt,int l,int r,int pos);void dfs(int u,int pre,int deep) {     int t= ++cnt;     seq[t] = deep;     first[u] = t;     F[t] = u;     father[u] = pre;      root[u] = insert(root[pre],1,len,gethash(w[u]));     for(int i= head[u];i!=-1;i = edge[i].next) {        int v = edge[i].v;        if(v == pre ) continue;        dfs(v,u,deep+1);        t = ++cnt;        seq[t] = deep;        F[t] = u;        }}void init_rmq(int n){ for(int i=1;i<=n;i++) dp[i][0]= i; for(int i=1;(1<<i)<=n;i++)   for(int j=1;j+(1<<i)-1 <= n;j++){     if(seq[dp[j][i-1]] < seq[dp[j+(1<<(i-1))][i-1]] ) dp[j][i] = dp[j][i-1];     else dp[j][i] = dp[j+(1<<(i-1))][i-1];    }}int lca(int a,int b) {  a = first[a];  b = first[b];  if(a>b) swap(a,b);  int l = (int)floor(log((b-a+1)*1.00)/log(2.00));  a = dp[a][l];  b = dp[b-(1<<l)+1][l];  if(seq[a] < seq[b]) return F[a];  else return  F[b];     }struct node { int l,r,sz;      }tree[M*40];int build(int l,int r) {  int k = ++ top;  tree[k].sz = 0;  if(l==r) return k;  int mid = ( l + r ) >> 1;  tree[k].l = build(l,mid) ;  tree[k].r = build(mid+1,r) ;  return k;  }int insert (int rt,int l,int r,int pos) {  int t = ++ top;  tree[t] = tree[rt] ;  tree[t].sz ++ ;  if(l == r ) return t ;  int mid = (l+r) >> 1;  if(pos <= mid ) tree[t].l = insert (tree[rt].l,l,mid,pos) ;  else tree[t].r = insert ( tree[rt].r,mid+1,r,pos) ;  return t;    }int query(int rt,int rta,int rtb,int l,int r,int k,int pos) { if ( l == r )  return lisan[l]; int mid = ( l+r ) >> 1; int temp = tree[tree[rta].l].sz + tree[tree[rtb].l].sz - tree[tree[rt].l].sz - tree[tree[pos].l].sz; if ( temp >= k ) return query(tree[rt].l,tree[rta].l,tree[rtb].l,l,mid,k,tree[pos].l) ; else return query(tree[rt].r,tree[rta].r,tree[rtb].r,mid+1,r,k-temp,tree[pos].r) ;} int main(){ int n,m; cin>>n>>m; init(); for(int i=1;i<=n;i++) scanf("%d",w+i),lisan[++len] = w[i]; int u,v,k; for(int i=1;i<n;i++) {    scanf("%d%d",&u,&v);    add(u,v);    add(v,u); }  init_hash();  root[0] = build(1,len) ;  dfs(1,0,0);  init_rmq(cnt);  while(m--)  {        scanf("%d%d%d",&u,&v,&k);        int lc = lca(u,v) ;        printf("%d\n",query(root[lc],root[u],root[v],1,len,k,root[father[lc]]));    }  return 0;}

原创粉丝点击