题目

有 \(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. 包管理器pacman常用方法

    详见[pacman(简体中文) - ArchWiki]:https://wiki.archlinux.org/title/Pacman_(简体中文) 更新系统: pacman -Syu 对整个系统进行 ...

  2. win7修改开机动画

    开机动画的修改 首先win7的过场动画是存在于C:\Windows\System32\bootres.dll ,而修改过程动画就需要修改这个dll,我不会改,所以只能用工具美化大师,软媒魔方里面的一个 ...

  3. elasticsearch 聚合之 date_histogram 聚合

    目录 1.背景 2.bucket_key如何计算 3.前置知识 4.日历和固定时间间隔 4.1 Calendar intervals 日历间隔 4.2 Fixed intervals 固定间隔 5.数 ...

  4. .NET周报【11月第4期 2022-11-30】

    国内文章 .NET 7 的 AOT 到底能不能扛反编译? https://www.cnblogs.com/huangxincheng/p/16917197.html 在B站,公众号上发了一篇 AOT ...

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

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

  6. windows安装grunt时提示不是内部或外部命令解决方案

    参考:https://www.cnblogs.com/hts-technology/p/8477258.html 安装windows安装elasticsearch-head时 不需要输入grunt s ...

  7. .NET 6 基于IDistributedCache实现Redis与MemoryCache的缓存帮助类

    本文通过IDistributedCache的接口方法,实现Redis与MemoryCache统一帮助类.只需要在配置文件中简单的配置一下,就可以实现Redis与MemoryCache的切换. 目录 I ...

  8. 《HTTP权威指南》– 3.HTTP方法和状态码

    常见HTTP方法: 常用HTTP方法 描述 是否包含主体 GET 从服务器获取一份文档 否 HEAD 只从服务器获取文档的首部 否 POST 向服务器发送需要处理的数据 是 PUT 将请求的主体部分存 ...

  9. PyTorch复现GoogleNet学习笔记

    PyTorch复现GoogleNet学习笔记 一篇简单的学习笔记,实现五类花分类,这里只介绍复现的一些细节 如果想了解更多有关网络的细节,请去看论文<Going Deeper with Conv ...

  10. [sklearn] 决策树、随机森林、隐马尔可夫模型

    决策树 决策树(Decision Tree)是一种用于处理分类和回归问题的无监督学习算法.如下图所示为某女青年在某相亲网站的相亲决策图.这幅图描述的都是一个非常典型的决策树模型. 通过对其相亲决策的分 ...