1821 最优集合

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ACM__dongsheng/article/details/62217888

一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S’,使得S’中元素之和为i。
给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2,以及一个数k,要求选择一个S2的子集S3(|S3|<=k),使得S1∪S3的优美值最大。
(集合元素可以重复)
Input

第一行一个数n,(n<=1000)
接下来n行,每行描述一个集合:
第一个数m,表示集合大小,接下来m个数,表示集合中的元素(m<=1000,元素<=10^9)
第n+2行一个数T,表示询问次数(T<=10000)
接下来T行,每行3个数a,b,k,表示指定第a个集合为S1,第b个集合为S2,k的意义如题(a<=n,b<=n,k<=100,000)

Output

T行,每行一个数,表示对应询问所能达到的最大优美值

Input示例

2
6 1 2 3 8 15 32
6 1 1 1 1 1 1
1
1 2 3

Output示例

64

/* 
    最优美值 为 s[j] + 1 < a[j+1] 的 s[j]
    如何从 集合b 中选出  一个  满足 x <= s[j]  +1  的最大值 
    对 b 进行排序 , 把满足  x<= s[j] 的值都放入stack中 。, stack.top() 就是   最大的 x; 
     对于  k 次 以上操作, 首先完成一次,更新 最优美值 。 
*/

#include <iostream>
#include <algorithm>
#include <stack>
#include <cstdio>
using namespace std;
int se[1005][1005];

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int main(){
    int n,m,k,t,a,b,num;
         n = read();
        for(int i=1;i<=n;i++){
            se[i][0] = read();
            for(int j=1;j<=se[i][0];j++) se[i][j] = read();
            sort(*(se+i)+1,*(se+i)+se[i][0]+1) ;
            se[i][se[i][0]+1] = 0 ; 
        }
        t = read();
        for(int i=0;i<t;i++){
            a = read(), b = read(), k = read();
            int size = se[a][0], z = 1;
            long long  btf = 0;
            stack<int> sta;

            for(int j=1;j<=size;j++){  
                 if(btf + 1 >= se[a][j]) {
                     btf = btf + se[a][j];
                     continue;
                 } 
                 else{
                    while(btf+1 < se[a][j] && k){
                    for(;btf+1 >= se[b][z] && z <= se[b][0];z++){    
                         sta.push(se[b][z]);
                    }
                    if(!sta.empty()){
                        btf += sta.top();
                        sta.pop();
                    }
                    k--;     
                   }
                 }  
                 if(btf + 1 >= se[a][j])  btf = btf + se[a][j];   
                 else break;
            }    
            while(k){  
                 if(!sta.empty() ){
                    btf += sta.top();
                    sta.pop();
                 }
                k--;
            }
            printf("%lld\n",btf);  
        }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/ACM__dongsheng/article/details/62217888