• Public Round #2 C 背包


    考虑写成暴力\(dp\)形式\(f_{i,j,k}\)\(i\) 的子树里,切了 \(j\) 条边,\(i\) 所在的联通块的权值为 \(k\) 是否可能

    我们考虑把其写做 \(d_{i,j} = \{k | f_{i,j,k}\}\)

    那么复杂度为 \(O(nk(siz)^2)\)

    考虑如何缩小其:

    • 首先发现 \(d_{i,j}\) 的极差为 \(i(R - L)\),因为其他不和 \(i\) 连的联通块的总和为 \([iL,iR]\),这样可以把 \(siz\) 减少到 \((k(R - L))\)

    • 发现若有 \(x < y < z\),且有 \(z - x <= R - L\), 那么 \(y\) 注定无用,即可以减少到 \(k\)

    点击查看代码
    //晦暗的宇宙,我们找不到光,看不见尽头,但我们永远都不会被黑色打倒。——Quinn葵因
    #include<bits/stdc++.h>
    #define ll long long
    #define N 1005
    
    using std::vector;
    using std::pair;
    #define pil pair<int,ll>
    
    vector<int>G[N];
    int n,k;
    ll L,R,val[N];
    
    int siz[N];
    
    vector<ll>f[N][51],tmp[51];
    
    ll gs[N << 5];
    
    inline void dfs(int u,int fa){
    	siz[u] = 1;
    	for(int i = 0;i <= k;++i)
    	f[u][i].clear();
    	f[u][0].push_back(val[u]);
    	for(auto v : G[u]){
    		if(v == fa)continue;
    		dfs(v,u);
    		for(int i = 0;i <= k;++i)tmp[i].clear();
    		for(int i = 0;i <= std::min(k,siz[u]);++i)
    		for(int j = 0;j <= std::min(k - i,siz[v]);++j)
    		for(ll I : f[u][i])for(ll J : f[v][j]){
    			if(I + J <= R)tmp[i + j].push_back(I + J);
    			if(J >= L && J <= R && i < k)tmp[i + j + 1].push_back(I);
    		}
    		siz[u] += siz[v];
    		for(int i = 0;i <= std::min(k,siz[u]);++i){
    			std::sort(tmp[i].begin(),tmp[i].end());
    			int cnt = 0;
    			for(ll t : tmp[i])gs[++cnt] = t;
    			cnt = std::unique(gs + 1,gs + cnt + 1) - gs - 1;
    			f[u][i].clear();
    			for(int j = 1;j <= cnt;++j)f[u][i].push_back(gs[j]);
    		}
    		
    	}
    }
    
    int main(){
    	int T ;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%lld%lld",&n,&k,&L,&R);
            for(int i=1;i<=n;i++) G[i].clear(),scanf("%lld",&val[i]);
            int x,y;
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&x,&y);
                G[x].push_back(y);
                G[y].push_back(x);
            }
            dfs(1,0);
            for(int i=0;i<=k;i++)
            {
                int flag=0;
                for(ll t:f[1][i]) if(t>=L && t<=R) flag=1;
                printf("%1d",flag);
            }
            printf("\n");
        }
        return 0;
    } 
    
  • 相关阅读:
    Delphi IDE 设置
    我最喜欢的歌曲
    Window 常用文件
    Delphi TTable 组件
    Delphi TDatabase 组件
    c语言->和 .
    Shell 工具之 gawk
    Shell 工具之 sed
    Shell 语法之函数
    Shell 语法之信号与作业
  • 原文地址:https://www.cnblogs.com/dixiao/p/16153831.html
Copyright © 2020-2023  润新知