题目

有 \(X+Y+Z\) 个三元组 \((x[i],y[i],z[i])\),请你从每个三元组中挑数,并满足以下条件:

1、每个三元组中可以且仅可以选择一个数(即 \(x[i],y[i],z[i]\) 中的一个)

2、选择 \(x[i]\) 的三元组个数恰好为 \(X\)

3、选择 \(y[i]\) 的三元组个数恰好为 \(Y\)

4、选择 \(z[i]\) 的三元组个数恰好为 \(Z\) 问选出的数的和最大是多少

问选出的数的和最大是多少

数据规模

对于10%的数据满足,\(1<=X+Y+Z<=15\)

对于30%的数据满足,\(1<=X+Y+Z<=100\)

对于另外10%的数据满足,\(X=0\)

对于另外20%的数据满足,所有三元组中的 \(x[i]=0\)

对于另外20%的数据满足,\(1<=X+Y+Z<=100000\)

对于100%的数据满足,\(1<=X+Y+Z<=500000,0<=x[i],y[i],z[i]<=500000\)

分析

这题真妙哉!!

首先考虑 \(X = 0\) 时的贪心

显然先强制选所有 \(y[i]\)

然后按 \(z_i - y_i\) 从大到小排序,选前 \(Z\) 格就行了

然后考虑 \(X > 0\)

先强制选所有 \(x[i]\)

按 \(z_i - y_i\) 从大到小排序

枚举一个分界点

在这之前(包括本身)选 \(Z\) 个 \(z[i]\),按 \(z[i]-x[i]\) 从大到小选

在这之后选 \(Y\) 个 \(y[i]\),按 \(y[i]-x[i]\) 从大到小选

这题就可做了

当然我们显然不可能一直排序

所以我们可以用数据结构维护一下

吸口氧就过了

用桶排序即可

那我们怎样统计每次的答案呢

我们考虑每次下移临界点时,\(z\) 的选择就多了一个 \(z[i]-x[i]\),\(y\) 的选择就少了一个 \(y[i]-x[i]\)

且只会这样

那么我们用双指针挪动就行

但实现细节不是那么容易

特别是 \(z[i]-x[i]\) 或是 \(y[i]-x[i]\) 有多个的时候

就要特别讨论

所以我们还有顺便维护选取的数是桶一个单元中的第几个

\(Code\)

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std; const int N = 500005;
int X, Y, Z, Tz[N << 1], Ty[N << 1], Add;
struct node{int x, y, z;}a[N];
inline bool cmp(node a, node b){return (a.z - a.y) > (b.z - b.y);} int main()
{
freopen("triple.in", "r", stdin);
freopen("triple.out", "w", stdout);
scanf("%d%d%d", &X, &Y, &Z);
LL ans = 0, sum = 0;
for(register int i = 1; i <= X + Y + Z; i++)
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z), sum += a[i].x, Add = max(Add, max(a[i].x, max(a[i].y, a[i].z)));
sort(a + 1, a + X + Y + Z + 1, cmp); int lz, rz, sz, ly, ry, sy;
lz = ly = Add << 1, rz = ry = 0;
for(register int i = 1; i <= Z; i++)
Tz[a[i].z - a[i].x + Add]++, lz = min(lz, a[i].z - a[i].x + Add), rz = max(rz, a[i].z - a[i].x + Add), sum += a[i].z - a[i].x;
sz = 1;
for(register int i = Z + 1; i <= X + Y + Z; i++)
Ty[a[i].y - a[i].x + Add]++, ly = min(ly, a[i].y - a[i].x + Add), ry = max(ry, a[i].y - a[i].x + Add);
for(register int i = ry, s = 0; i >= ly; i--)
if (Ty[i])
{
s += Ty[i], sum += 1LL * (i - Add) * Ty[i];
if (s >= Y){ly = i, sy = Ty[i] - (s - Y), sum -= 1LL * (i - Add) * (s - Y); break;}
} ans = sum;
for(register int i = Z + 1; i <= X + Z; i++)
{
int del = a[i].z - a[i].x + Add;
Tz[del]++;
if (del >= lz)
{
sum += (del - Add) - (lz - Add);
if (del > rz) rz = del;
if (sz == Tz[lz])
{
++lz, sz = 1;
while (lz < rz && !Tz[lz]) ++lz;
}
else ++sz;
} del = a[i].y - a[i].x + Add;
if (del >= ly)
{
sum -= del - Add;
if (sy >= Ty[ly])
{
--ly, sy = 1;
while (ly && !Ty[ly]) --ly;
sum += ly - Add;
}
else sum += ly - Add, ++sy;
}
Ty[del]--;
ans = max(ans, sum);
}
printf("%lld\n", ans);
}

JZOJ 5432. 【NOIP2017提高A组集训10.28】三元组的更多相关文章

  1. 5432. 【NOIP2017提高A组集训10.28】三元组

    题目 题目大意 给你\(X+Y+Z\)个三元组\((x_i,y_i,z_i)\). 然后选\(X\)个\(x_i\),选\(Y\)个\(y_i\),选\(Z\)个\(z_i\). 每个三元组只能选择其 ...

  2. [JZOJ 5437] [NOIP2017提高A组集训10.31] Sequence 解题报告 (KMP)

    题目链接: http://172.16.0.132/senior/#main/show/5437 题目: 题解: 发现满足上述性质并且仅当A序列的子序列的差分序列与B序列的差分序列相同 于是我们把A变 ...

  3. 5433. 【NOIP2017提高A组集训10.28】图

    题目描述 Description 有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x ...

  4. 【JZOJ5428】【NOIP2017提高A组集训10.27】查询

    题目 给出一个长度为n的序列a[] 给出q组询问,每组询问形如\(<x,y>\),求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个. 分析 我们可以维护一个前缀和 ...

  5. 【JZOJ5439】【NOIP2017提高A组集训10.31】Calculate

    题目 分析 对于\[\sum_{i=1}^{n}\lfloor\dfrac{T-B_i}{A_i}\rfloor\] 我们考虑拆开处理,得到 \[\sum_{i=1}^{n}(\lfloor\dfra ...

  6. 【JZOJ5430】【NOIP2017提高A组集训10.27】图

    题目 有一个n个点的无向图,给出m条边,每条边的信息形如\(<x,y,c,r>\) 给出q组询问形如\(<u,v,l,r>\) 接下来解释询问以及边的意义 询问表示,一开始你在 ...

  7. 【JZOJ5434】【NOIP2017提高A组集训10.30】Matrix

    题目 分析 假设答案为ans, 发现\[k=\sum_{i=1}^{min(n,k)}\lfloor \dfrac{ans}{i} \rfloor\] 于是可以对ans进行二分, 用分块来求出上面的式 ...

  8. 【NOIP2017提高A组集训10.21】Fantasy

    题目 Y sera 陷入了沉睡,幻境中它梦到一个长度为N 的序列{Ai}. 对于这个序列的每一个子串,定义其幻境值为这个子串的和,现在Y sera 希望选择K 个不同的子串并使得这K 个子串的幻境值之 ...

  9. JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠

    JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...

  10. JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线

    JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...

随机推荐

  1. Python3.7.3安装TensorFlow和OpenCV3

    根据python的版本进行下载相应的文件 一.安装TensorFlow 进入网址https://pypi.org/project/tensorflow/#files下载TensorFlow文件 进入下 ...

  2. 【Shell案例】【!~//、grep反向查找、sed流编辑器】13、去掉所有包含this的句子

    描述写一个 bash脚本以实现一个需求,去掉输入中含有this的语句,把不含this的语句输出示例:假设输入如下:that is your bagis this your bag?to the deg ...

  3. 【大数据课程】高途课程实践-Day02:利用Hive SQL编写离线数仓实现可视化展示

    〇.概述 1.实现内容 使用Hive SQL编程,构造分层离线数仓 并可以通过Quick Bi进行展示 2.过程 (1)数据接⼊到ODS层 (2)进⾏ODS到DWD层数据开发 (3)进⾏ODS到DIM ...

  4. python中的数学函数

  5. static_cast和dynamic_cast

    C++的强制类型转换,除了继承自C语言的写法((目标类型)表达式)之外,还新增了4个关键字,分别是:static_cast.dynamic_cast.const_cast和reinterpret_ca ...

  6. js迭代循环

    一.for loop for (let i = 0; i < products.length; i++) { console.log(products[i]); } 支持循环中断,可以用brea ...

  7. 判断条件为NULL

    在ASCII码表里NULL的二进制位0.所以NULL作为判断条件时,表示为假的意思. ASCII表               二进制                       字符         ...

  8. 【进阶篇】Redis实战之Jedis使用技巧详解

    一.摘要 在上一篇文章中,我们详细的介绍了 redis 的安装和常见的操作命令,以及可视化工具的介绍. 刚知道服务端的操作知识,还是远远不够的,如果想要真正在项目中得到应用,我们还需要一个 redis ...

  9. [编程基础] Python模块和包使用笔记

    本文探讨Python模块和Python包,这两种机制有助于模块化编程. 模块化编程是指将大型笨拙的编程任务分解为单独的,较小的,更易于管理的子任务或模块的过程.然后可以像构建模块一样将各个模块拼凑在一 ...

  10. [seaborn] seaborn学习笔记2-散点图Scatterplot

    2 散点图Scatterplot(代码下载) 散点图能够显示2个维度上2组数据的值.每个点代表一个观察点.X(水平)和Y(垂直)轴上的位置表示变量的值.研究这两个变量之间的关系是非常有用的.在seab ...