6438. [01.16] GDOI2020 tree murine analog (long chain split)

Title Description

Description

Input

Output

Sample Input
3
1 2
1 3

Sample Output
2

Explanation
only if the communication blocks or the entire tree is only one little Yao lose, win Yao small remaining cases.

Data Constraint

answer

A communication block losing the upper hand, if and only if a diameter at the midpoint of the diameter and length is odd

prove:

If the length is odd and not at the midpoint, the upper hand can be moved to the midpoint, the other can be moved to shift no matter how the diameter of the point of symmetry

If the length of the case is even, the upper hand can be moved to the midpoint far as the moving distance of the opponent next> 1 can not be moved to another midpoint, the odd similar

Set \ (F [i] [j] \) represents the root to the point i, the maximum depth is the number j of the subtree, and finally combined at a

Clearly related to the depth dp is a long chain split, the \ (f [u] [1 \ sim x] \) and \ (F [V] [. 1 \ SIM Y] \) ( \ (X> Y \) ) merge, for \ (1 \ sim y \) portion violence were combined, then \ (y + 1 \) at the number on the back of a reward by suffix numerals

Maintenance can be directly transferred when \ (f \) suffix value, the final answer is calculated using the total - is not legitimate, then a similar dp can calculate the number of illegal

至于状态的保存,因为一条链的状态数=链长,所以可以按深度从上到下存到树上,表示深度1,2,3...时的\(f\),在上传重儿子时也只需考虑新加的那一个点

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 998244353
#define file
using namespace std;

int a[2000001][2];
int b[1000002];
int c[1000002];
int ls[1000001];
int dp[1000001];
int fa[1000001];
bool bz[1000001];
int d[1000001];
int I[1000001];
int nx[1000001];
long long g[1000001];
long long f[1000001];
long long F[1000001];
int st[1000001];
long long Ans[1000001][3];
long long Ans2[1000001];
int n,i,j,k,l,len,h,t,tot;
long long ans;

void New(int x,int y)
{
    ++len;
    a[len][0]=y;
    a[len][1]=ls[x];
    ls[x]=len;
}

void bfs()
{
    int i,mx,mx2;
    
    h=0;t=1;
    d[1]=1;
    bz[1]=1;
    
    while (h<t)
    {
        for (i=ls[d[++h]]; i; i=a[i][1])
        if (!bz[a[i][0]])
        {
            fa[a[i][0]]=d[h];
            
            bz[a[i][0]]=1;
            d[++t]=a[i][0];
        }
    }
    
    fd(l,t,1)
    {
        mx=0;mx2=-1;
        g[d[l]]=1;
        
        for (i=ls[d[l]]; i; i=a[i][1])
        if (a[i][0]!=fa[d[l]])
        {
            g[d[l]]=g[d[l]]*(g[a[i][0]]+1)%mod;
            
            if (dp[a[i][0]]>mx)
            mx=dp[a[i][0]],mx2=a[i][0];
        }
        
        nx[d[l]]=mx2;
        dp[d[l]]=mx+1;
    }
    ans=g[1];
}

void down(int t)
{
    f[t]=f[t]*F[t]%mod;
    if (nx[t]!=-1)
    F[nx[t]]=F[nx[t]]*F[t]%mod;
    F[t]=1;
}

void dfs(int st)
{
    int T,i,j,k,l;
    long long sum,s1,s2;
    
    t=1;
    d[1]=st;
    
    while (t)
    {
        T=d[t];
        
        if (nx[T]!=-1 && bz[T])
        {
            bz[T]=0;
            d[++t]=nx[T];
        }
        else
        if (I[T])
        {
            if (a[I[T]][0]==fa[T] || a[I[T]][0]==nx[T])
            I[T]=a[I[T]][1];
            else
            {
                d[++t]=a[I[T]][0];
                I[T]=a[I[T]][1];
            }
        }
        else
        {
            if (fa[T]!=1)
            {
                if (nx[fa[T]]==T)
                f[fa[T]]=(f[T]*F[T]+1)%mod;
                else
                {
                    tot=0;
                    i=fa[T];j=T;
                    
                    while (j!=-1)
                    {
                        ++tot;
                        b[tot]=i;c[tot+1]=j;
                        
                        down(i);down(j);
                        i=nx[i];j=nx[j];
                    }
                    b[++tot]=i;
                    down(i);
                    
                    sum=s1=s2=0;
                    if (nx[i]!=-1)
                    {
                        s1=f[nx[i]]*F[nx[i]]%mod;
                        
                        sum=f[nx[i]]*F[nx[i]]%mod*f[T]%mod;
                        F[nx[i]]=F[nx[i]]*(f[T]+1)%mod;
                    }
                    
                    fd(i,tot,2)
                    {
                        sum=(sum+(f[b[1]]-s1)*(f[c[2]]+1-s2)-(f[b[1]]-f[b[i]])*(f[c[2]]+1-f[c[i]])-(f[b[i]]-s1))%mod;
                        
                        s1=f[b[i]];s2=f[c[i]];
                        f[b[i]]=(f[b[i]]+sum)%mod;
                    }
                    f[b[1]]=(f[b[1]]+sum)%mod;
                }
            }
            --t;
        }
    }
}

int main()
{
    freopen("tree.in","r",stdin);
    #ifdef file
    freopen("tree.out","w",stdout);
    #endif
    
    scanf("%d",&n);
    Ans2[1]=Ans[1][0]=f[1]=F[1]=1;
    fo(i,2,n)
    {
        scanf("%d%d",&j,&k);
        Ans2[i]=Ans[i][0]=f[i]=F[i]=1;
        
        New(j,k);
        New(k,j);
    }
    
    fo(i,1,n) I[i]=ls[i];
    
    bfs();
    for (i=ls[1]; i; i=a[i][1])
    dfs(a[i][0]);
    
    for (i=ls[1]; i; i=a[i][1])
    {
        j=a[i][0];
        tot=1;
        
        while (j!=-1)
        {
            down(j);
            
            b[++tot]=j;
            j=nx[j];
        }
        b[tot+1]=0;
        
        Ans2[tot+1]=Ans2[tot+1]*(f[b[2]]+1)%mod;
        
        fo(j,2,tot)
        {
            Ans[j][2]=(Ans[j][2]*(f[b[2]]-f[b[j+1]]+1))%mod;
            
            fd(k,1,0)
            {
                Ans[j][k+1]=(Ans[j][k+1]+Ans[j][k]*(f[b[j]]-f[b[j+1]]))%mod;
                Ans[j][k]=Ans[j][k]*(f[b[2]]-f[b[j]]+1)%mod;
            }
        }
    }
    
    --ans;
    fo(i,2,n)
    {
        ans=(ans-Ans[i][2]*Ans2[i])%mod;
        Ans2[i+1]=Ans2[i+1]*Ans2[i]%mod;
    }
    
    printf("%lld\n",(ans+mod)%mod);
}

Guess you like

Origin www.cnblogs.com/gmh77/p/12204071.html