一个集合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;
}