zoukankan      html  css  js  c++  java
  • 【主席树】bzoj2588 Spoj 10628. Count on a tree

    每个点的主席树的root是从其父转移来的。询问的时候用U+V-LCA-FA(LCA)即可。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100001
    int v[N<<1],first[N],next[N<<1],en,Ans;
    void AddEdge(int U,int V)
    {
    	v[++en]=V;
    	next[en]=first[U];
    	first[U]=en;
    }
    struct Point{int v,p;}t[N];
    bool operator < (Point a,Point b){return a.v<b.v;}
    int n,m,ma[N],a[N],zy;
    struct Node{int v,lc,rc;}T[N*24];
    int root[N],e=1;
    void BuildTree(int cur,int l,int r)
    {
    	if(l==r) return;
    	int m=(l+r>>1);
    	T[cur].lc=++e;
    	BuildTree(T[cur].lc,l,m);
    	T[cur].rc=++e;
    	BuildTree(T[cur].rc,m+1,r);
    }
    void Insert(int pre,int cur,int p,int l,int r)
    {
    	if(l==r)
    	  {
    	  	T[cur].v=T[pre].v+1;
    	  	return;
    	  }
    	int m=(l+r>>1);
    	if(p<=m)
    	  {
    	  	T[cur].lc=++e;
    	  	T[cur].rc=T[pre].rc;
    	  	Insert(T[pre].lc,T[cur].lc,p,l,m);
    	  }
    	else
    	  {
    	  	T[cur].rc=++e;
    	  	T[cur].lc=T[pre].lc;
    	  	Insert(T[pre].rc,T[cur].rc,p,m+1,r);
    	  }
    	T[cur].v=T[T[cur].lc].v+T[T[cur].rc].v;
    }
    int top[N],siz[N],son[N],fa[N],dep[N];
    void df1(int U)
    {
    	siz[U]=1;
    	for(int i=first[U];i;i=next[i])
    	  if(v[i]!=fa[U])
    	    {
    	      fa[v[i]]=U;
    	      dep[v[i]]=dep[U]+1;
    	      df1(v[i]);
    	      siz[U]+=siz[v[i]];
    	      if(siz[v[i]]>siz[son[U]])
    	        son[U]=v[i];
    	    }
    }
    void df2(int U)
    {
    	if(son[U])
    	  {
    	  	top[son[U]]=top[U];
    	  	df2(son[U]);
    	  }
    	for(int i=first[U];i;i=next[i])
    	  if(v[i]!=fa[U]&&v[i]!=son[U])
    	    {
    	      top[v[i]]=v[i];
    	      df2(v[i]);
    	    }
    }
    int lca(int U,int V)
    {
    	while(top[U]!=top[V])
    	  {
    	  	if(dep[top[U]]<dep[top[V]])
    	  	  swap(U,V);
    	  	U=fa[top[U]];
    	  }
    	if(dep[U]>dep[V])
    	  swap(U,V);
    	return U;
    }
    void dfs(int U)
    {
    	root[U]=++e;
    	Insert(root[fa[U]],root[U],a[U],1,zy);
    	for(int i=first[U];i;i=next[i])
    	  if(v[i]!=fa[U])
    	    dfs(v[i]);
    }
    int Kth(int ql,int qr,int LCA,int FLCA,int K,int l,int r)
    {
    	if(l==r) return l;
    	int m=(l+r>>1);
    	if(T[T[ql].lc].v+T[T[qr].lc].v-T[T[LCA].lc].v-T[T[FLCA].lc].v>=K)
    	  return Kth(T[ql].lc,T[qr].lc,T[LCA].lc,T[FLCA].lc,K,l,m);
    	else
    	  return Kth(T[ql].rc,T[qr].rc,T[LCA].rc,T[FLCA].rc,K-(T[T[ql].lc].v+T[T[qr].lc].v-T[T[LCA].lc].v-T[T[FLCA].lc].v),m+1,r);
    }
    int main()
    {
    	int X,Y,W;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    	  {
    	  	scanf("%d",&t[i].v);
    	  	t[i].p=i;
    	  }
    	sort(t+1,t+n+1);
    	a[t[1].p]=++zy;
    	ma[zy]=t[1].v;
    	for(int i=2;i<=n;++i)
    	  {
    	  	if(t[i].v!=t[i-1].v) ++zy;
    	  	a[t[i].p]=zy;
    	  	ma[zy]=t[i].v;
    	  }
    	for(int i=1;i<n;++i)
    	  {
    	  	scanf("%d%d",&X,&Y);
    	  	AddEdge(X,Y);
    	  	AddEdge(Y,X);
    	  }
    	root[0]=1;
    	BuildTree(root[0],1,zy);
    	df1(1);
    	top[1]=1;
    	df2(1);
    	dfs(1);
    	for(;m;--m)
    	  {
    	  	scanf("%d%d%d",&X,&Y,&W); X^=Ans;
    	  	int t=lca(X,Y);
    	  	printf("%d",Ans=ma[Kth(root[X],root[Y],root[t],root[fa[t]],W,1,zy)]);
    	    if(m!=1) puts("");
    	  }
    	return 0;
    }
  • 相关阅读:
    SDUT-3376_数据结构实验之查找四:二分查找
    SDUT-3375_数据结构实验之查找三:树的种类统计
    SDUT-3373_数据结构实验之查找一:二叉排序树
    深度优先遍历和广度优先遍历
    SDUT-2498_AOE网上的关键路径
    SDUT-2140_判断给定图是否存在合法拓扑序列
    SDUT-2144_最小生成树
    SDUT-3364_欧拉回路
    SDUT-3363_驴友计划
    Java练习 SDUT-2271_Eddy的难题
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4422979.html
Copyright © 2011-2022 走看看