n個のノードのツリー、およびnの配置所与の(B [i])と、与えられた配列よりも厳密に小さいためDFS方式における木の数を見つけます。N <= 1E6
これは、1つです。。ツリービットDP&A、我々はデジタルDP、OKビットずつの考えに従ってください。
X無制限に根付いた木は、それがどのように多くのDFSの順だ場合はまず、我々は、ほとんど無制限の場合を考えます。
これは明らかにルートDPを変更することができます。まず、サブツリーDP。集合$ F [X] $が答え、その後、利用できるの$ F [X] =息子である[X]!息子[X]は息子の数を表し、[息子] $ F \タイムズ\ prodに。
これは、より理解することができる完全なサブツリーDFSモチーフを横断する現在のセクションに分割することができる表し制限はないので、各セクションは、DFSの息子であり、セグメント部が関係に整列されます。
その後、我々は、ツリー全体の回答のルートを見つけるために、再度ルートDP xを変更することができます。
Bに列挙1 [1] -1 Fその答えに参加。
次に、rootとしてB [1]検討してください。
私たちは今、問題を解決するために、DFSを使用し、問題は根のb値の配列を決定することであり、木は、サブプログラムの数よりも厳密に小さいです。
その後、我々は次の層に鍋の上にダンプされ、その後、再帰的に解決することを目指し、DFSを入力します。いくつかのものをダンプすることはできません。しかし、この層は、対処しなければなりません。
設定された現在位置がlenです
クラスについての最初のポイント。
LEN 1.は、+ 1未満になります。この層は、この問題を解決することができ、以下の最初の段落を見つけることができ、状況、つまり、どのように多くの人の息子<B [lenは+ 1]、その後、CNTを想定し、その後、最初の段落そこにCNTの場合、その他の構成は、まだ疲れていると掛けます。
2. 1が言うだろう再帰的な問題である息子のサブツリーで未満を開始します。
3.スタートは、以下次のように息子のB列の現在位置よりも、その後、二つのサブ木はいくつかの木のシーケンスで覆われている直前に、例えば、息子から次の選挙の範囲であった、それがあるべきマイナス息子の総数それは完全残りは選挙の息子の数を取得することができるように、私は現在のすべてのビット数の選挙で見つけることができる、息子の数でカバーされた、最初の状況Bの息子よりも少ないです*その他の構成と疲れ掛けます。
だから我々は第二の問題を解決するため、ストロークのB列に沿って検討してください。
私たちは、サイクルの息子を行いました。
各サイクルの内部次いで、投稿息子を取るために1つずつのB配列に相当する、第LEN + 1と比べてシーケンスした後にBを位置決めするためのカバーとして、[後期]遅く息子からBに等しい子を見つけるために次の私たちは息子のサブツリーが完全にB、休憩に固執することはできません息子、ポットの決定的な拒否の制限内順列の数を見つけ、問題を発見し、同じ問題を提示します。
しかし、我々は、サブツリーの息子はB、それに貼付され、ツリー全体のサイズのドットを扱うことができないを判断する方法、問題に走りましたか?
我々は、サブサブツリーのこの息子木は、それはフルサイズのBに取り付けることができるかどうかを記録するために何かを必要と我々は、これも再帰的に解決することができることを見出しました
イェジンハオは、グローバル変数は、私のDFSがフラグを返すために、短いで、ペースト全体を表すことができないかどうかを変更し、DFSとリターン構造は、このフラグが1、即ち、の息子をbに取り付けられたすべての人の息子を注文することができなければならないですフラグは、私は本当に倍の息子だった、と途中休憩から落ちていなかったの前に特定の実装がサイクルの息子である、1です。ループをbに等しいの息子を見つけることができない場合はもちろん、[後半]破ることがあります。
その後、いくつかのアイデアに沿って:3種類、飼料の第1のタイプはさえDFS終了することができる、第二のタイプは、[後半]息子とシーケンスに固執することができ、すべてを列挙することによって決定され、DFS、もし、私の蓄積をbに等しいですその後、それは遅+ =サイズ[息子]、第三のカテゴリーで、この息子に取り付けられており、蓄積された配列に対応するがB未満で次の息子の答えからの答えは、答えよりも厳密な下始まる息子のサブツリー、そして、次のサイクルの終わりまで......答え未満の息子のB [後半]サブツリーに等しい見つけます。
回答の計算2月3日カテゴリーを渡ります。
リーフノードを再帰的フラグに処理する場合、私はそれ以外の場合、B 1、0の現在の値に等しい場合、その値は、私は[LEN] 1は、再帰チェーンを示すために戻されるBよりも小さい場合、戻り値は、であることこれは、より厳密に少なくすることができます。
その後、問題が解決されます。
しかし、ガチョウはT.なります
观察一下数据范围,1e6,但是在dfs的过程中是对于每个点我进行了两层循环,也就是说每个点被作为儿子枚举了n次,复杂度是$O(n^{2})$的,复杂度瓶颈卡在了我在找一个儿子是否等于b[late]的时候是枚举所有儿子的,接下来就很简单了,用一个数据结构维护一下每个点的儿子,支持删除,和单点,区间查询,splay和sgtree都可以,但我觉得动态开点的sgtree好写(得多)。然后就能A了。
#include<cstring> #include<iostream> #include<cstdio> #define ll long long using namespace std; const int N=300020,mod=1e9+7; int fr[N],b[N],son[N],size[N],fa[N],flag,tt,n; ll f[N],fac[N]; bool v[N]; struct node{int to,pr;}mo[N*2]; long long rd() { long long s=0,w=1; char cc=getchar(); while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();} while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar(); return s*w; } ll inv(ll a) { ll ans=1,k=mod-2; for(;k;k>>=1,a=1ll*a*a%mod) if(k&1) ans=1ll*ans*a%mod; return ans; } void add(int x,int y) { mo[++tt].to=y; mo[tt].pr=fr[x]; fr[x]=tt; } void first_dfs(int x) { ll ans=1;size[x]=1; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x])continue; son[x]++; fa[to]=x; first_dfs(to); ans=1ll*ans*f[to]%mod; size[x]+=size[to]; } f[x]=1ll*fac[son[x]]*ans%mod; } void re_dfs(int x) { for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; //cout<<x<<" "<<to<<endl; //cout<<to<<" "<<1ll*f[x]%mod*inv[f[to]]%mod<<endl; //cout<<son[to]<<endl; f[to]=1ll*f[to]*f[x]%mod*inv(f[to])%mod*inv(son[x])%mod*(++son[to])%mod; re_dfs(to); } } ll dfs(int len,int x) { if(son[x]==0) { flag=x==b[len]; return x<b[len]; } long long ans=0,sum=0; for(int i=fr[x];i;i=mo[i].pr) if(mo[i].to!=fa[x]&&mo[i].to<b[len+1])sum++; //cout<<ans<<endl; ans=(ans+1ll*sum*f[x]%mod*inv(son[x])%mod)%mod; //cout<<x<<" "<<ans<<endl; ll lat=len+1,pi=1ll*f[x]*inv(fac[son[x]])%mod;sum=son[x]; //cout<<x<<" "<<" "<<lat<<endl; flag=1; for(int k=1;k<=son[x];k++) { bool jud=0; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; //cout<<to<<" "<<b[lat]<<endl; if(to==b[lat]) { v[to]=1; pi=pi*inv(f[to])%mod; long long tmp=dfs(lat,to); ans=(ans+1ll*tmp*fac[sum-1]%mod*pi%mod)%mod; // cout<<to<<" "<<b[lat]<<" "<<tmp<<" "<<flag<<endl; lat=lat+size[to],sum--; jud=1; break; } } if(!flag) break; if(!jud) break; int cnt=0; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; if(v[to]) continue; if(to<b[lat]) cnt++; } //cout<<b[lat]<<" s"<<cnt<<" "<<sum<<" "<<pi<<" "<<ans<<endl; if(sum!=son[x])ans=(ans+1ll*pi*cnt%mod*fac[sum-1]%mod)%mod; //cout<<ans<<endl; } if(flag==1&&sum==0) flag=1; else flag=0; return ans; } ll solve() { ll ans=0; first_dfs(1); re_dfs(1); for(int i=1;i<b[1];i++)ans=(ans+f[i])%mod; //cout<<ans<<endl; memset(son,0,sizeof(son)); memset(fa,0,sizeof(fa)); memset(f,0,sizeof(f)); memset(size,0,sizeof(size)); first_dfs(b[1]); ans=(ans+dfs(1,b[1]))%mod; return ans; } int main() { //freopen("travel2.in","r",stdin); //freopen("data1.in","r",stdin); //freopen("data1.out","w",stdout); n=rd();fac[0]=1; for(int i=1;i<=n;i++)b[i]=rd(),fac[i]=1ll*fac[i-1]*i%mod; for(int i=1,x,y;i<n;i++) { x=rd(),y=rd(); add(x,y);add(y,x); } printf("%lld\n",solve()); } /* g++ -std=c++11 1.cpp -o 1 ./1 6 1 3 6 2 5 4 1 2 1 3 1 4 4 5 1 6 */
#include<cstring> #include<iostream> #include<cstdio> #define ll long long using namespace std; const int N=300020,mod=1e9+7; int fr[N],b[N],son[N],size[N],fa[N],flag,tt,n; ll f[N],fac[N]; bool v[N]; struct node{int to,pr;}mo[N*2]; long long rd() { long long s=0,w=1; char cc=getchar(); while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();} while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar(); return s*w; } ll inv(ll a) { ll ans=1,k=mod-2; for(;k;k>>=1,a=1ll*a*a%mod) if(k&1) ans=1ll*ans*a%mod; return ans; } void add(int x,int y) { mo[++tt].to=y; mo[tt].pr=fr[x]; fr[x]=tt; } void first_dfs(int x) { ll ans=1;size[x]=1; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x])continue; son[x]++; fa[to]=x; first_dfs(to); ans=1ll*ans*f[to]%mod; size[x]+=size[to]; } f[x]=1ll*fac[son[x]]*ans%mod; } void re_dfs(int x) { for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; //cout<<x<<" "<<to<<endl; //cout<<to<<" "<<1ll*f[x]%mod*inv[f[to]]%mod<<endl; //cout<<son[to]<<endl; f[to]=1ll*f[to]*f[x]%mod*inv(f[to])%mod*inv(son[x])%mod*(++son[to])%mod; re_dfs(to); } } ll dfs(int len,int x) { if(son[x]==0) { flag=x==b[len]; return x<b[len]; } long long ans=0,sum=0; for(int i=fr[x];i;i=mo[i].pr) if(mo[i].to!=fa[x]&&mo[i].to<b[len+1])sum++; //cout<<ans<<endl; ans=(ans+1ll*sum*f[x]%mod*inv(son[x])%mod)%mod; //cout<<x<<" "<<ans<<endl; ll lat=len+1,pi=1ll*f[x]*inv(fac[son[x]])%mod;sum=son[x]; //cout<<x<<" "<<" "<<lat<<endl; flag=1; for(int k=1;k<=son[x];k++) { bool jud=0; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; //cout<<to<<" "<<b[lat]<<endl; if(to==b[lat]) { v[to]=1; pi=pi*inv(f[to])%mod; long long tmp=dfs(lat,to); ans=(ans+1ll*tmp*fac[sum-1]%mod*pi%mod)%mod; // cout<<to<<" "<<b[lat]<<" "<<tmp<<" "<<flag<<endl; lat=lat+size[to],sum--; jud=1; break; } } if(!flag) break; if(!jud) break; int cnt=0; for(int i=fr[x];i;i=mo[i].pr) { int to=mo[i].to; if(to==fa[x]) continue; if(v[to]) continue; if(to<b[lat]) cnt++; } //cout<<b[lat]<<" s"<<cnt<<" "<<sum<<" "<<pi<<" "<<ans<<endl; if(sum!=son[x])ans=(ans+1ll*pi*cnt%mod*fac[sum-1]%mod)%mod; //cout<<ans<<endl; } if(flag==1&&sum==0) flag=1; else flag=0; return ans; } ll solve() { ll ans=0; first_dfs(1); re_dfs(1); for(int i=1;i<b[1];i++)ans=(ans+f[i])%mod; //cout<<ans<<endl; memset(son,0,sizeof(son)); memset(fa,0,sizeof(fa)); memset(f,0,sizeof(f)); memset(size,0,sizeof(size)); first_dfs(b[1]); ans=(ans+dfs(1,b[1]))%mod; return ans; } int main() { //freopen("travel2.in","r",stdin); //freopen("data1.in","r",stdin); //freopen("data1.out","w",stdout); n=rd();fac[0]=1; for(int i=1;i<=n;i++)b[i]=rd(),fac[i]=1ll*fac[i-1]*i%mod; for(int i=1,x,y;i<n;i++) { x=rd(),y=rd(); add(x,y);add(y,x); } printf("%lld\n",solve()); } /* g++ -std=c++11 1.cpp -o 1 ./1 6 1 3 6 2 5 4 1 2 1 3 1 4 4 5 1 6 */