• 51nod1821-最优集合【贪心】


    正题

    题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1821


    题目大意

    (n)个可重集合,(T)次询问,询问将集合(S_x)和一个选出大小为(k)(S_y)的子集合并成的独立集(S')满足能够找到一个最大的(z)使得对于任意的正整数(iin [1,z])都存在一个(S')的子集和为(i)

    (1leq n,m_ileq 1000,1leq Tleq 10000)


    解题思路

    考虑我们已经拼出了一个(z),那么我们如果加入一个(leq z+1)的数(x)那么就可以使得上限变成(z+x)
    所以可以考虑贪心,因为第一个集合没有限制我们就优先选择第一个集合里的数,直到不能选择我们就选择第二个集合里的直到能够继续选择第一个集合里的。
    排好序然后开个栈维护就好了。
    时间复杂度(O(nmlog m+Tm))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=1100;
    ll n,T,m[N],s[N],a[N][N];
    signed main()
    {
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		scanf("%lld",&m[i]);
    		for(ll j=1;j<=m[i];j++)
    			scanf("%lld",&a[i][j]);
    		sort(a[i]+1,a[i]+1+m[i]);
    	}
    	scanf("%lld",&T);
    	while(T--){
    		ll x,y,k,z=1,top=0,sum=1,flag=0;
    		scanf("%lld%lld%lld",&x,&y,&k);
    		for(ll i=1;i<=m[x];i++){
    			while(z<=m[y]&&a[y][z]<=sum)s[++top]=a[y][z],z++;
    			while(sum<a[x][i]){
    				if(!k||!top){flag=1;break;}
    				sum+=s[top];k--;top--;
    			}
    			if(flag)break;sum+=a[x][i];
    		}
    		while(k&&top)sum+=s[top],top--,k--;
    		printf("%lld
    ",sum-1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Python操作Excel,使用xlwings
    TortoiseGit的使用
    QsLog日志
    状态机 1748一次遍历
    socket理解
    __gcd函数,求最大公约数
    opencv resize的一个小问题
    iOS要想访问工程里的资源文件
    iOS 真机socket连不上问题
    要看
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15087919.html
Copyright © 2020-2023  润新知