树上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; }
spoj cot Count on a tree
最新推荐文章于 2020-12-04 16:42:41 发布