[缩树 主席树] BZOJ 4539 [Hnoi2016]树

来源:互联网 发布:数据分析师培训机构 编辑:程序博客网 时间:2024/05/21 08:41

hnoi的大数据结构题

把每一个残基缩一下 变成一颗大树 

每次新增

查询一下是在哪个残基上 这里要用主席树求子树第k大

然后记一下到fat的权值

然后就各种细节搞lca


#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  return *p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline void read(ll &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;#define V G[p].vnamespace tree1{  struct edge{    int u,v,next;  }G[N<<2];  int head[N],inum;  inline void add(int u,int v,int p){    G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;  }  inline void link(int u,int v){    add(u,v,++inum); add(v,u,++inum);  }  const int K=21;  int fat[N][K],depth[N];  int clk,pre[N],bac[N],size[N];  inline void dfs(int u,int fa){    pre[u]=++clk; bac[clk]=u; size[u]=1;    fat[u][0]=fa; depth[u]=depth[fa]+1;      for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];      for (int p=head[u];p;p=G[p].next)      if (V!=fa)dfs(V,u),size[u]+=size[V];  }  inline int LCA(int u,int v){      if (depth[u]<depth[v]) swap(u,v);      for (int k=K-1;~k;k--)        if ((depth[u]-depth[v])&(1<<k))  u=fat[u][k];      if (u==v) return u;      for (int k=K-1;~k;k--)        if (fat[u][k]!=fat[v][k])  u=fat[u][k],v=fat[v][k];      return fat[v][0];    }  inline int Dist(int u,int v){    return depth[u]+depth[v]-2*depth[LCA(u,v)];  }}namespace tree2{  struct edge{    int u,v,w,next;  }G[N<<2];  int head[N],inum;  inline void add(int u,int v,int w,int p){    G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;  }  inline void link(int u,int v,int w){    add(u,v,w,++inum); add(v,u,w,++inum);  }  const int K=21;  int fat[N][K],depth[N]; ll dis[N];  int clk,pre[N],bac[N],size[N];  inline void dfs(int u,int fa){    pre[u]=++clk; bac[clk]=u; size[u]=1;    fat[u][0]=fa; depth[u]=depth[fa]+1;      for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];      for (int p=head[u];p;p=G[p].next)      if (V!=fa)dis[V]=dis[u]+G[p].w,dfs(V,u),size[u]+=size[V];  }  inline int LCA(int u,int v){      if (depth[u]<depth[v]) swap(u,v);      for (int k=K-1;~k;k--)        if ((depth[u]-depth[v])&(1<<k))  u=fat[u][k];      if (u==v) return u;      for (int k=K-1;~k;k--)        if (fat[u][k]!=fat[v][k])  u=fat[u][k],v=fat[v][k];      return fat[v][0];    }  inline int Fat(int u,int lca){    for (int k=K-1;~k;k--)      if (depth[fat[u][k]]>depth[lca])u=fat[u][k];    return u;  }  inline ll Dist(int u,int v){    return dis[u]+dis[v]-2*dis[LCA(u,v)];  }}namespace Seg{  int root[N],ncnt;  int ls[N*21],rs[N*21],sum[N*21];  inline void Add(int &x,int y,int l,int r,int t){    if (!x) x=++ncnt; int mid=(l+r)>>1;    if (l==r){      sum[x]=sum[y]+1;      return;    }    if (t<=mid)      Add(ls[x],ls[y],l,mid,t),rs[x]=rs[y];    else      Add(rs[x],rs[y],mid+1,r,t),ls[x]=ls[y];    sum[x]=sum[ls[x]]+sum[rs[x]];  }  inline int Query(int x,int y,int l,int r,int k){    if (l==r) return l; int mid=(l+r)>>1;    if (k<=sum[ls[y]]-sum[ls[x]])      return Query(ls[x],ls[y],l,mid,k);    else      return Query(rs[x],rs[y],mid+1,r,k-(sum[ls[y]]-sum[ls[x]]));  }}int n,m,Q;inline void Init(){  using namespace tree1;  for (int i=1;i<=n;i++)    Seg::Add(Seg::root[i],Seg::root[i-1],1,n,bac[i]);}inline int Query(int u,int k){  using namespace tree1;  return Seg::Query(Seg::root[pre[u]-1],Seg::root[pre[u]+size[u]-1],1,n,k);}int fcnt,ft[N],ff[N];ll fl[N],fr[N];inline int belong(ll idx){  return lower_bound(fr+1,fr+fcnt+1,idx)-fr;}inline void Link(int a,ll b){  int rt=belong(b);  int ch=Query(ft[rt],b-fl[rt]+1);  ++fcnt; ft[fcnt]=a; fl[fcnt]=fr[fcnt-1]+1; fr[fcnt]=fr[fcnt-1]+tree1::size[a]; ff[fcnt]=ch;  tree2::link(rt,fcnt,tree1::depth[ch]-tree1::depth[ft[rt]]+1);}inline ll Dis(ll u){  int rt=belong(u);  int ch=Query(ft[rt],u-fl[rt]+1);  return tree2::dis[rt]+tree1::depth[ch]-tree1::depth[ft[rt]];}inline void Solve(ll a,ll b){  ll ret=Dis(a)+Dis(b),tem=0;  int rta=belong(a),rtb=belong(b),lca=tree2::LCA(rta,rtb);  if (lca==rta && lca==rtb){    int cha=Query(ft[rta],a-fl[rta]+1),chb=Query(ft[rtb],b-fl[rtb]+1);    int t=tree1::LCA(cha,chb);    tem+=tree2::dis[lca];    tem+=tree1::depth[t]-tree1::depth[ft[lca]];  }  else if (lca==rta || lca==rtb){    if (rtb==lca) swap(rtb,rta),swap(a,b);    int cha=Query(ft[rta],a-fl[rta]+1),chb=tree2::Fat(rtb,lca);    int t=tree1::LCA(cha,ff[chb]);    tem+=tree2::dis[lca];    tem+=tree1::depth[t]-tree1::depth[ft[lca]];  }else{    int cha=tree2::Fat(rta,lca),chb=tree2::Fat(rtb,lca);    int t=tree1::LCA(ff[cha],ff[chb]);    tem+=tree2::dis[lca];    tem+=tree1::depth[t]-tree1::depth[ft[lca]];  }  printf("%lld\n",ret-2*tem);}int main(){  int iu,iv; ll ia,ib;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(m); read(Q);  for (int i=1;i<n;i++){    read(iu); read(iv);    tree1::link(iu,iv);  }  tree1::dfs(1,0);  Init();  fcnt=1; fl[1]=1; fr[1]=n; ft[1]=1;  for (int i=1;i<=m;i++){    read(iu); read(ib);    Link(iu,ib);  }  tree2::dfs(1,0);  while (Q--){    read(ia); read(ib);    Solve(ia,ib);  }  return 0;}


0 0
原创粉丝点击