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独特的树叶的主要内容,如果未能解决你的问题,请参考以下文章