您的位置:首页 > 其它

51nod 1821 最优集合(贪心+并查集)

2017-09-13 20:16 281 查看
1821 最优集合


基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题


 收藏


 关注

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






﹡    LH (题目提供者)

Visual C++的运行时限为:1000 ms ,空间限制为:131072 KB 示例及语言说明请按这里

 允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章

对于一个集合的优美值now而言,假如存在一个集合的优美值为x并且x<=now+1的话,

呢两个集合加起来的优美值一定是now+x,因此我们在找第一个集合优美值的同时,

在第二个集合中每次贪心的找最大不超过now+1的子集合加入到集合1中,但是每次从头找回很耗时,

我们可以采取一些优化策略,比如标记这个数之前没用过的最大的数,可以用并查集搞搞。

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
#define ll long long
#define inf 1000000000
#define mod 1000000007
#define maxn 1008
#define lowbit(x) (x&-x)
#define eps 1e-9
ll a[maxn][maxn],parent[maxn];
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 find(int x)
{
if(parent[x]==x)
return x;
return parent[x]=find(parent[x]);
}
void solve(int p,int q,int k)
{
int i=1,j=1,x,now=0;
while(1)
{
if(i<=a[p][0] && a[p][i]<=now+1)
now+=a[p][i],i++;
else
{
if(k<=0)
break;
k--;
while(j<=a[q][0] && a[q][j]<=now+1)
j++;
j--;x=find(j);
if(x==0)
break;
now+=a[q][x];
parent[x]=find(x-1);
if(x==j)
j++;
}
}
printf("%d\n",now);
}
int main(void)
{
int n,k,i,j,x,y,T;
n=read();
for(i=1;i<=n;i++)
{
a[i][0]=read();
for(j=1;j<=a[i][0];j++)
a[i][j]=read();
sort(a[i]+1,a[i]+a[i][0]+1);
}
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&x,&y,&k);
for(i=0;i<=1002;i++)
parent[i]=i;
solve(x,y,k);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: