CF1111E Tree Dynamic Programming + LCT

This idea is very good question.    

$ K $ we can point out, it is required to $ k $ points are divided into not more than $ m $ program number set.   

Order $ f [i] [j] $ represents the front dividing $ $ I $ points to the program number of sets J $.  

Then there is $ f [i] [j] = f [i-1] [j-1] + f [i-1] [j] * (j-fail [i]) $, where $ fail [i] $ $ I $ representative of the number of ancestors of this path root.             

And $ fail [i] $ embodiment are solved: Virtual statistics / management path tree data structure and, where selected LCT used to maintain. 

code: 

#include <cstdio> 
#include <cstring> 
#include <vector>
#include <algorithm>  
#define N 100007   
#define ll long long 
#define mod 1000000007 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
namespace LCT 
{    
    #define lson t[x].ch[0] 
    #define rson t[x].ch[1] 
    struct node 
    {
        int ch[2],f,rev,sum,val;       
    }t[N];     
    you sta [N];  
    int get(int x) 
    {
        return t[t[x].f].ch[1]==x; 
    }                                    
    int isrt(int x) 
    {
        return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); 
    }
    void pushup(int x) 
    {
        t[x].sum=t[lson].sum+t[rson].sum+t[x].val; 
    }  
    void mark(int x) 
    {  
        t[x].rev^=1; 
        swap(lson,rson);    
    }  
    void pushdown(int x) 
    { 
        if(t[x].rev) 
        {
            if(lson) mark(lson); 
            if(rson) mark(rson); 
            t[x].rev=0; 
        }
    }
    void rotate(int x) 
    {
        int old=t[x].f,fold=t[old].f,which=get(x);            
        if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x;  
        t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;  
        t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; 
        pushup(old),pushup(x); 
    }    
    void splay(int x) 
    { 
        int v = 0, u = x ago;           
        for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f;            
        for (; v; - v) pushdown (sta [v]); 
        for(u=t[u].f;(fa=t[x].f)!=u;rotate(x)) 
        {
            if(t[fa].f!=u)
                rotate(get(fa)==get(x)?fa:x);  
        }
    }
    void Access(int x) 
    {
        for(int y=0;x;y=x,x=t[x].f) 
        {
            splay(x); 
            rson = y; 
            pushup(x);  
        }
    }
    Void makeroot (int x) 
    {
        Access(x),splay(x),mark(x); 
    }   
    void split(int x,int y) 
    {
        makeroot (x), Access (y), splay (y);  
    }
    void add(int x,int v) 
    {
        Access(x),splay(x); 
        t[x].val+=v,pushup(x);        
    }
    int query(int x) 
    {           
        Access(x),splay(x);  
        return t[x].sum;   
    }
    #undef lson 
    #undef rson 
}; 
int n,edges; 
int hd[N],to[N<<1],nex[N<<1],f[N],A[N],dp[N][302];     
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;    
}
void dfs(int u,int ff) 
{
    LCT::t[u].f=ff;  
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==ff) continue;  
        dfs (v, u); 
    }  
}
int main () 
{ 
    // setIO("input");      
    int i,j,q; 
    scanf("%d%d",&n,&q);  
    for(i=1;i<n;++i) 
    {   
        int x,y; 
        scanf("%d%d",&x,&y);  
        add(x,y),add(y,x);   
    }  
    dfs(1,0); 
    for(i=1;i<=q;++i) 
    {
        int k,m,r,flag=0; 
        scanf("%d%d%d",&k,&m,&r); 
        LCT :: makeroot (r);   
        for(j=1;j<=k;++j) 
        {
            scanf("%d",&A[j]);    
            LCT::add(A[j],1);              
        }   
        for(j=1;j<=k;++j) 
        {      
            f[j]=LCT::query(A[j])-1;        
            if(f[j]>m) flag=1;             
        } 
        for(j=1;j<=k;++j)  LCT::add(A[j],-1); 
        if(flag)   printf("0\n"); 
        else 
        {        
            sort(f+1,f+1+k);    
            dp[1][1]=1;   
            for(j=2;j<=k;++j) 
            {      
                for(int p=1;p<=min(j,m);++p) 
                {
                    dp[j][p]=0; 
                    if(p<f[j])   dp[j][p]=dp[j-1][p-1];  
                    else dp[j][p]=(ll)(dp[j-1][p-1]+1ll*(p-f[j])*dp[j-1][p]%mod)%mod;               
                }
            }
            int years = 0;   
            for(j=1;j<=m;++j)  ans=(ans+dp[k][j])%mod;  
            printf("%d\n",ans); 
        }
    }
    return 0; 
}

  

Guess you like

Origin www.cnblogs.com/guangheli/p/12091045.html