题意:一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S',使得S'中元素之和为i。

给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2,以及一个数k,要求选择一个S2的子集S3(|S3|<=k),使得S1∪S3的优美值最大。
(集合元素可以重复)
 
我们首先考虑对于集合S1,能否求出它的最大优美值。
  首先排序一遍,对于前i个元素,如果它的最大优美值为v,那么当S1[i+1]>v+1时,前i+1个元素的最大优美值依然为v,否则为v+S1[i+1].此处易证。
  也就是说集合S1的最大优美值等于排序后集合S1的使得S1[i+1]>Sum[i]+1成立的最大前缀和.
再考虑S2到底加入哪些元素可以使得S1的优美值最大呢。
  首先可以肯定的是,由于加入的元素数量有限制,因此S2应该尽量加对S1的优美值增加最大的元素,由上面可以得知,应该为使得S2[i]<=v+1的最大的S2[i].
  这样之后v就变成了v+S2[i],此时集合S1又有可能有元素可以利用了,这样一直进行K次。
要确保算法复杂度即可能低的情况下,可以使用单调队列来维护上面的操作。
因此,总时间复杂度为O(log(nm)+T*m).
 
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... VI v[N];
LL val[N], que[N];
int p[N], head, tail; void sol(int x, int &q, LL &w){
FO(i,q,v[x].size()) {
if (v[x][i]>w+) break;
w+=v[x][i]; ++q;
}
}
int main ()
{
int n, m, x, A, B, K, T;
n=Scan();
FOR(i,,n) {
m=Scan();
while (m--) x=Scan(), v[i].pb(x);
sort(v[i].begin(),v[i].end());
p[i]=m;
FO(j,,v[i].size()) {
if (v[i][j]>val[i]+) {p[i]=j; break;}
val[i]+=v[i][j];
}
}
T=Scan();
while (T--) {
A=Scan(); B=Scan(); K=Scan();
int q=p[A];
LL w=val[A];
head=-; tail=;
FO(i,,v[B].size()) {
while (v[B][i]>w+) {
if (head<tail || !K) break;
if (head>=tail&&K) w+=que[head], sol(A,q,w), --head, --K;
}
if (v[B][i]<=w+) {
que[++head]=v[B][i];
while (head-tail+>K) ++tail;
}
if (head<tail || !K) break;
}
if (K) while (head>=tail) w+=que[tail], sol(A,q,w), ++tail;
printf("%lld\n",w);
}
return ;
}

51nod 1821 最优集合(思维+单调队列)的更多相关文章

  1. 51NOD 1821 最优集合 栈

    1821 最优集合   一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S',使得S'中元素之和为i. 给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2, ...

  2. 51NOD 1821 最优集合 [并查集]

    传送门 题意: 一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S',使得S'中元素之和为i. 给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2,以及一个 ...

  3. 【洛谷】【动态规划+单调队列】P1725 琪露诺

    [题目描述:] 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河 ...

  4. poj 1821 Fence(单调队列优化DP)

    poj 1821 Fence \(solution:\) 这道题因为每一个粉刷的人都有一块"必刷的木板",所以可以预见我们的最终方案里的粉刷匠一定是按其必刷的木板的顺序排列的.这就 ...

  5. poj 1821 Fence 单调队列优化dp

    /* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...

  6. 51nod 1275 连续字段的差异(单调队列)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1275 题意: 思路: 固定某个端点,然后去寻找满足能满足要求的最大区间, ...

  7. 51nod 1050 循环数组最大子段和 单调队列优化DP

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 这个呢,这个题之前 求一遍最大值  然后求一遍最小值 ...

  8. POJ - 1821 单调队列优化DP + 部分笔记

    题意:n个墙壁m个粉刷匠,每个墙壁至多能被刷一次,每个粉刷匠要么不刷,要么就粉刷包含第Si块的长度不超过Li的连续墙壁(中间可不刷),每一块被刷的墙壁都可获得Pi的利润,求最大利润 避免重复粉刷: 首 ...

  9. POJ 1821 单调队列+dp

    题目大意:有K个工人,有n个墙,现在要给墙涂色.然后每个工人坐在Si上,他能刷的最大范围是Li,且必须是一个连续子区间,而且必须过Si,他刷完后能获得Pi钱 思路:定义dp[i][j]表示前i个人,涂 ...

随机推荐

  1. 20155308&20155316 2017-2018-1 《信息安全系统设计基础》实验一

    20155308&20155316 2017-2018-1 <信息安全系统设计基础>实验一 此次实验我和黄月同学一起做了1.2.3.5项,第4项在实验课上做完了,但是没有按时提交. ...

  2. 20155328 《Java程序设计》实验三 敏捷开发与XP实践 实验报告

    一.编码标准 编程标准包含:具有说明性的名字.清晰的表达式.直截了当的控制流.可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性. 下面是没有最基本的缩进的一个程序: publi ...

  3. python 生成随机长度的字符串

    import os def randomString(n): return (''.join(map(lambda xx:(hex(ord(xx))[2:]),os.urandom(n))))[0:1 ...

  4. 1111: [POI2007]四进制的天平Wag

    1111: [POI2007]四进制的天平Wag 链接 题意: 用一些四进制数,相减得到给定的数,四进制数的数量应该尽量少,满足最少的条件下,求方案数. 分析: 这道题拖了好久啊. 参考Claris的 ...

  5. cogs87 乘积最大

    cogs87 乘积最大 原题链接 题解 竟然不用高精... f[i][j]表示前i位数j个乘号的最大数f[i][j]=max{f[i-l][j-1]*num[i-l+1][i]} num[a][b]表 ...

  6. NPOI读取Excel到集合对象

    之前做过的项目中有个需要读取Excel文件内容的需求,因此使用NPOI实现,写下以下代码,这个只是一个代码段,还有很多地方需要优化,希望能对大家有所帮助 public static IList< ...

  7. MySQL数据库之数据类型和完整性约束

    补充: select * from mysql.user #显示出来乱了 select * from mysql.user\G #加了\G后一行一行显示了 一.数据类型:分不同种类去存不同类型的数据 ...

  8. JUC——ThreadFactory线程工厂类(四)

    ThreadFactory线程工厂类 在默认情况下如果要想创建一个线程类对象,大部分情况的选择是:直接通过子类为父类进行实例化,利用Runnable子类为Runnable接口实例化. 或者直接调用La ...

  9. Windows操作系统C盘占用空间过多

    Windows操作系统C盘占用空间过多 大部分的windows电脑用户在长时间使用PC时都会遇到一个问题,就是C盘占用的空间会越来越多,乃至占满整个C盘. 后来在百度了一波,发现各种方法都试过了,也不 ...

  10. IBM基于Kubernetes的容器云全解析

    基于Kubernetes的容器云 容器云最主要的功能是以应用为中心,帮助用户把所有的应用以容器的形式在分布式里面跑起来,最后把应用以服务的形式呈现给用户.容器云里有两个关键点,一是容器编排,二是资源调 ...