其他分享
首页 > 其他分享> > 【JSOI2016】独特的树叶

【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;
    }
  }
}

 

标签:lb,rb,JSOI2016,树叶,int,uLL,ans,return,独特
来源: https://www.cnblogs.com/shxnb666/p/11279738.html