Tree-bit DP

  Given a tree of n nodes, and an arrangement of n (b [i]), find the number of trees in order DFS schemes strictly less than the given arrangement. n <= 1e6

  This is one. . Tree-bit DP & A, we follow the idea of ​​digital DP, bit by bit OK.

  First, we consider the case of most no limit, if a tree rooted at x unlimited, it's how many DFS order.

  This can obviously change the root DP. First sub-tree DP. Set $ ​​f [x] $ is the answer, then the available $ f [x] = son [x]! \ Times \ prod f [son] $ where son [x] represents the number of sons.

  This can be appreciated from that represents the current to traverse the complete subtree DFS motif can be divided into a section, each section is a son of DFS, and the segment section is aligned relation, because there is no limitation.

  Then we can change the root DP x again to find the root of the entire tree answers.

  Enumeration 1 to b [1] -1 f join their answers.

  Then consider b [1] as the root.

  We now use a dfs to solve the problem, the problem is to sequence a b value of the root, the tree is strictly less than the number of sub-programs.

  Then enter dfs, we aim to be dumped on the pot to the next layer, and then recursively resolve. But some things can not be dumped, this layer must be addressed.

  Set the current position is len

  First points about class.

  1. From len + 1 will be less than: This layer can solve this problem, the situation may find the following first paragraph, that is, how many sons <b [len + 1], then assumed cnt, then the first paragraph there cnt case, the rest of the arrangement is still tired and multiply.

  2. Start less than in the sub-tree of a son, which is a recursive problem one will say.

  3. Start ranged from a son, for example, just before the two sub-trees are covered with some trees sequence, then the next election less than a son b sequence current position as the next one, then it should be minus the total number of son it has been completely covered by the number of sons, so that the rest can get a number of sons of the election, then I can find in the election of all current bit number is less than b son, is the first one situation * the rest of the arrangement and tired multiply.

  So we consider along the b array of stroke, solve the second problem.

  We conducted a son of cycles.

  Inside each cycle to find a son equal to b [late], late son as a cover to position b after the sequence, compared with the first len ​​+ 1, corresponds to the sequence b one by one to take his son posted, then next we found a problem and present the same problem, find the number of permutations within the limits of the son, decisive rejection of the pot, when the sub-tree of a son can not completely stick to the b, break.

  But we ran into a problem, how to judge the son of a sub tree can not handle the whole tree size dots affixed to the b it? 

  We need something to record whether this son of sub-sub-tree a tree, it can be attached to the full-size b, we found that this also may be recursively solved,

  Return structure with dfs Ye Hao, global variables modify whether, in short my dfs to return a flag, can not represent the whole paste, this flag is 1 must be able to order all the sons affixed to b, that is, the son of flag is 1, the specific implementation is the son of cycles before I really was the son of times, and did not fall from the middle break. Of course, if the loop can not find a son equal to b [late] have to break.

  Then along some ideas: three types, a first type of feed may be finished even dfs, is the second type is equal to b [late] son ​​and dfs determined by enumerating all can stick to the sequence, if, I accumulation son subtree beginning strictly lower than answers, then subsequently it late + = size [son], corresponding to the sequence attached to this son, and accumulated at the third category is the answer from the next son answer at less than b, then find the next is equal to a son b [late] subtree less than answer ...... until the end of the cycle.

  Cross the calculation February 3 categories of answers.

  When the leaf node to recursively process In Flag, if I is equal to the current value of b 1, 0 otherwise, and that the return value, if the value is less than I b [len] 1 is returned to indicate a recursive chain is It can be strictly less than the.

  Then the problem is solved.

  However, the goose will be 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
*/
80pts更容易理解
#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
*/
100pts

 

Guess you like

Origin www.cnblogs.com/starsing/p/11401623.html