zoukankan      html  css  js  c++  java
  • 【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;
        }
      }
    }
  • 相关阅读:
    Executing a system tool
    arcengine帮助http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/what_s_new_for_developers_at_10_/0001000002zp000000/
    Arcgis10.2中复制后粘贴图标是灰色的,无法粘贴,编辑也打开了,如何解决?
    VB.net X86设置
    elasticsearch5.5.2安装
    破解极验(geetest)验证码
    solidity代码
    2017年保荐代表人胜任能力考试辅导教材 投资银行业务
    投资银行业务过关必做1500题
    《一站到底》题库及答案
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11279738.html
Copyright © 2011-2022 走看看