JSOI2016独特的树叶

Posted shxnb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSOI2016独特的树叶相关的知识,希望对你有一定的参考价值。

题面

https://loj.ac/problem/2072

题解

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#define N 100500
#define uLL unsigned long long
#define ri register int

using namespace std;
const uLL p=107;
set<uLL> s;
uLL pp[N];

bool cmp1(int x,int y); 

struct tree 
  unsigned long long f[N],g[N];
  int siz[N],fa[N];
  vector<int> son[N],to[N];
  vector<uLL> sum1[N],sum2[N];
  
  void add_edge(int u,int v) 
    to[u].push_back(v); to[v].push_back(u);
  
  void maketree(int x,int ff) 
    fa[x]=ff;
    siz[x]=1;
    for (ri i=0,l=to[x].size();i<l;i++) if (to[x][i]!=ff) 
      son[x].push_back(to[x][i]);
      sum1[x].push_back(0);
      sum2[x].push_back(0);
      maketree(to[x][i],x);
      siz[x]+=siz[to[x][i]];
    
  
  void dp1(int x) 
    if (son[x].size()==0) 
      f[x]=1;
      return;
    
    for (ri i=0,l=son[x].size();i<l;i++) dp1(son[x][i]);
    sort(&son[x][0],&son[x][son[x].size()],cmp1);
    uLL fac=1;
    for (ri i=0,l=son[x].size();i<l;i++) 
      sum1[x][i]=(i==0?0:sum1[x][i-1])+fac*f[son[x][i]];
      f[x]+=(fac*f[son[x][i]]);
      fac*=p;
    
    f[x]*=siz[x];
    int l=son[x].size()-1;fac=1;
    for (ri i=l;i>=0;i--) sum2[x][i]=(i==l?0:sum2[x][i+1]*p)+f[son[x][i]];
  
  inline uLL s1(int x,int y)
    if (y==-1) return 0; else return sum1[x][y];
  
  inline uLL s2(int x,int y)
    int l=son[x].size();
    if (y==l) return 0; else return sum2[x][y];
  
  inline uLL getval(int x,int lb,int rb) 
    if (lb>rb) return 0;
    return sum2[x][lb]-s2(x,rb+1)*pp[rb-lb+1];
  
  inline int search(int x,uLL v) 
    int ans=son[x].size(),lb=0,rb=ans-1;
    while (lb<=rb) 
      int mid=(lb+rb)/2;
      if (f[son[x][mid]]>=v) ans=mid,rb=mid-1; else lb=mid+1;
    
    return ans;
  
  void dp2(int x) 
    int ff=fa[x];
    int p1=search(ff,f[x]);
    int p2=search(ff,g[ff]);
    if (p1<p2) g[x]=s1(ff,p1-1)+getval(ff,p1+1,p2-1)*pp[p1]+g[ff]*pp[p2-1]+s2(ff,p2)*pp[p2];
    else g[x]=s1(ff,p2-1)+g[ff]*pp[p2]+getval(ff,p2,p1-1)*pp[p2+1]+s2(ff,p1+1)*pp[p1+1];
    g[x]*=(uLL)(siz[1]-siz[x]);
    for (ri i=0,l=son[x].size();i<l;i++) dp2(son[x][i]);
  
  void work() 
    maketree(1,-1);
    dp1(1);
    g[1]=0;
    for (ri i=0,l=son[1].size();i<l;i++) 
      int x=son[1][i];
      if (son[1].size()==1) 
        g[x]=1;
      
      else 
        g[x]=s1(1,i-1)+s2(1,i+1)*pp[i];
        g[x]*=(uLL)(siz[1]-siz[x]);
      
      for (ri j=0,l2=son[x].size();j<l2;j++) dp2(son[x][j]);
    
  
 A;
bool cmp1(int x,int y) return A.f[x]<A.f[y];

bool cmp2(int x,int y);
struct tree2 
  unsigned long long f[N],g[N];
  int siz[N],fa[N];
  vector<int> son[N],to[N];
  vector<uLL> sum1[N],sum2[N];
  
  void add_edge(int u,int v) 
    to[u].push_back(v); to[v].push_back(u);
  
  void maketree(int x,int ff) 
    fa[x]=ff;
    siz[x]=1;
    for (ri i=0,l=to[x].size();i<l;i++) if (to[x][i]!=ff) 
      son[x].push_back(to[x][i]);
      sum1[x].push_back(0);
      sum2[x].push_back(0);
      maketree(to[x][i],x);
      siz[x]+=siz[to[x][i]];
    
  
  void dp1(int x) 
    if (son[x].size()==0) 
      f[x]=1;
      return;
    
    for (ri i=0,l=son[x].size();i<l;i++) dp1(son[x][i]);
    sort(&son[x][0],&son[x][son[x].size()],cmp2);
    uLL fac=1;
    for (ri i=0,l=son[x].size();i<l;i++) 
      sum1[x][i]=(i==0?0:sum1[x][i-1])+fac*f[son[x][i]];
      f[x]+=(fac*f[son[x][i]]);
      fac*=p;
    
    f[x]*=siz[x];
    int l=son[x].size()-1;fac=1;
    for (ri i=l;i>=0;i--) sum2[x][i]=(i==l?0:sum2[x][i+1]*p)+f[son[x][i]];
  
  inline uLL s1(int x,int y)
    if (y==-1) return 0; else return sum1[x][y];
  
  inline uLL s2(int x,int y)
    int l=son[x].size();
    if (y==l) return 0; else return sum2[x][y];
  
  inline uLL getval(int x,int lb,int rb) 
    if (lb>rb) return 0;
    return sum2[x][lb]-s2(x,rb+1)*pp[rb-lb+1];
  
  inline int search(int x,uLL v) 
    int ans=son[x].size(),lb=0,rb=ans-1;
    while (lb<=rb) 
      int mid=(lb+rb)/2;
      if (f[son[x][mid]]>=v) ans=mid,rb=mid-1; else lb=mid+1;
    
    return ans;
  
  void dp2(int x) 
    int ff=fa[x];
    int p1=search(ff,f[x]);
    int p2=search(ff,g[ff]);
    if (p1<p2) g[x]=s1(ff,p1-1)+getval(ff,p1+1,p2-1)*pp[p1]+g[ff]*pp[p2-1]+s2(ff,p2)*pp[p2];
    else g[x]=s1(ff,p2-1)+g[ff]*pp[p2]+getval(ff,p2,p1-1)*pp[p2+1]+s2(ff,p1+1)*pp[p1+1];
    g[x]*=(uLL)(siz[1]-siz[x]);
    for (ri i=0,l=son[x].size();i<l;i++) dp2(son[x][i]);
  
  void work() 
    maketree(1,-1);
    dp1(1);
    g[1]=0;
    for (ri i=0,l=son[1].size();i<l;i++) 
      int x=son[1][i];
      if (son[1].size()==1) 
        g[x]=1;
      
      else 
        g[x]=s1(1,i-1)+s2(1,i+1)*pp[i];
        g[x]*=(uLL)(siz[1]-siz[x]);
      
      for (ri j=0,l2=son[x].size();j<l2;j++) dp2(son[x][j]);
    
  
 B;
bool cmp2(int x,int y) return B.f[x]<B.f[y];

int main()
  int u,v,n;
  scanf("%d",&n);
  pp[0]=1;
  for (ri i=1;i<N;i++) pp[i]=pp[i-1]*p;
  for (ri i=1;i<n;i++) 
    scanf("%d %d",&u,&v);
    A.add_edge(u,v);
  
  A.work();
  for (ri i=1;i<=n;i++) 
    scanf("%d %d",&u,&v);
    B.add_edge(u,v);
  
  B.work();
  s.clear();
  for (ri i=1;i<=n;i++) 
    uLL ans=0,fac=1;
    bool fir=0;
    for (ri j=0,l=A.son[i].size();j<l;j++) 
      if (A.f[A.son[i][j]]>A.g[i] && !fir && i!=1) ans+=A.g[i]*fac,fac*=(uLL)p,fir=1;
      ans+=A.f[A.son[i][j]]*fac;
      fac*=(uLL)p;
    
    if (!fir && i!=1) ans+=A.g[i]*fac,fac*=(uLL)p,fir=1;
    //cout<<i<<" "<<ans<<endl;
    s.insert(ans);
  
  //cout<<endl;
  for (ri i=1;i<=n+1;i++) if (B.to[i].size()==1) 
    int x=B.to[i][0];
    uLL ans=0,fac=1;
    bool fir=0;
    for (ri j=0,l=B.son[x].size();j<l;j++) if (B.son[x][j]!=i) 
      if (B.f[B.son[x][j]]>B.g[x] && B.fa[x]!=i && !fir && x!=1) ans+=B.g[x]*fac,fac*=(uLL)p,fir=1;
      ans+=B.f[B.son[x][j]]*fac;
      fac*=(uLL)p;
    
    if (!fir && B.fa[x]!=i && x!=1) ans+=B.g[x]*fac,fac*=(uLL)p,fir=1;
    //cout<<i<<" "<<ans<<endl;
    if (s.count(ans)) 
      cout<<i<<endl;
      return 0;
    
  

 

以上是关于JSOI2016独特的树叶的主要内容,如果未能解决你的问题,请参考以下文章

[JSOI2016]独特的树叶

bzoj 4754: [Jsoi2016]独特的树叶

bzoj4754: [Jsoi2016]独特的树叶

Luogu P4323 [JSOI2016]独特的树叶

独特的树叶

独特的树叶