• BZOJ 5072: [Lydsy1710月赛]小A的树 树形DP


    这个题有一个结论:如果用 $x$ 个点能凑出的给点个数在 $[L,R]$ 之间,那么任意 $vin [L,R]$ 一定能取到. 

    知道这个结论之后跑一个树形背包就行了,注意在跑背包的时候上界一定要限制好,要不然时间复杂度会多一个 $O(n)$ 的.  

    code: 

    #include <cstdio> 
    #include <string>   
    #include <cstring>
    #include <algorithm>    
    #define N 5020   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;     
    int n,edges;   
    int hd[N],to[N<<1],nex[N<<1],size[N],f[N][N],g[N][N],ff[N],gg[N],v[N],sf[N],sg[N];    
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
    } 
    void clr() 
    {
        edges=0;  
        memset(hd,0,sizeof(hd)); 
        memset(nex,0,sizeof(nex)); 
    }      
    void dfs(int u,int fa) 
    {   
        size[u]=1; 
        f[u][1]=g[u][1]=v[u];  
        for(int i=hd[u];i;i=nex[i]) 
        {
            int y=to[i]; 
            if(y==fa) continue;   
            dfs(y,u);             
            memcpy(ff,f[u],sizeof(f[u])); 
            memcpy(gg,g[u],sizeof(g[u]));  
            for(int j=1;j<=size[u];++j) 
            {
                for(int k=1;k<=size[y];++k) 
                {          
                    ff[j+k]=max(ff[j+k],f[u][j]+f[y][k]);   
                    gg[j+k]=min(gg[j+k],g[u][j]+g[y][k]); 
                }
            } 
            size[u]+=size[y];
            for(int j=1;j<=size[u];++j) f[u][j]=ff[j], g[u][j]=gg[j];       
        }    
        for(int i=1;i<=size[u];++i)   sf[i]=max(sf[i],f[u][i]), sg[i]=min(sg[i],g[u][i]);   
    }
    void solve() 
    {
        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); 
        }     
        for(i=1;i<=n;++i) scanf("%d",&v[i]);   
        memset(f,0xc0,sizeof(f)), memset(g,0x3f,sizeof(g)); 
        memset(sf,0xc0,sizeof(sf)), memset(sg,0x3f,sizeof(sg));      
        dfs(1,0);          
        for(i=1;i<=Q;++i) 
        { 
            int x,y; 
            scanf("%d%d",&x,&y);  
            if(y>=sg[x]&&y<=sf[x]) printf("YES
    "); 
            else printf("NO
    "); 
        }
        printf("
    ");  
        clr();   
    }
    int main() 
    { 
        // setIO("input"); 
        int i,j,T; 
        scanf("%d",&T); 
        while(T--) solve(); 
        return 0; 
    }
    

      

  • 相关阅读:
    泛型
    事件和委托
    参数和属性
    常量、字段、和方法
    LINQ
    LINQ- 子查询、组合策略、投影策略
    MySQL全局锁和表锁
    CLR基础
    LINQ
    LINQ
  • 原文地址:https://www.cnblogs.com/guangheli/p/12133175.html
Copyright © 2020-2023  润新知