【NOIP2017提高A组集训10.28】三元组
来源:互联网 发布:淘宝店铺保证金多少钱 编辑:程序博客网 时间:2024/05/18 17:56
Description:
有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问选出的数的和最大是多少
问选出的数的和最大是多少.
1<=X+Y+Z<=500000,0<=x[i],y[i],z[i]<=500000
题解:
其实这题的部分给了一些很明显的提示,但是没有仔细想。
假设X=0,这个问题就变成了二元问题。
那一个有点可撤销意思的贪心就是假设全部选了y,那么对于每一个y[i],我不要它的代价就是z[i]-y[i],那么我选出最大的Z个z[i]-y[i]就行了。
对于三元问题,可行的思路就是假设全部选了x,那么要选从X+Y+Z个中选出最大的Y个y[i]-x[i]和Z个z[j]-x[j](i ≠ j)。
发现其实这个问题也不好做。
如果按z[i]-y[i]从大到小排序。
你会感受到选z[i]的一定在前面,选y[i]的一定在后面。
即不会存在
所以枚举z[i]-y[i]的分界线,从分界线前选最大的Z个z[i]-x[i],从分界线后选最大的Y个y[i]-x[i],当然可以上数据结构,但是这题卡时,就必须用基数排序了。
Code:
#include<cstdio>#include<cstring>#define ll long long#define fo(i, x, y) for(int i = x; i <= y; i ++)#define fd(i, x, y) for(int i = x; i >= y; i --)#define $ N +#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))using namespace std;const int N = 5e5 + 50;int x0, y0, z0, n, x[N], y[N], z[N], x1[N];int final[N * 2], to[N], next[N], tot;void link(int x, int y) { next[++ tot] = final[x], to[tot] = y, final[x] = tot;}int d[N], t[N * 2];ll s1[N], s2[N];int main() { freopen("triple.in", "r", stdin); freopen("triple.out", "w", stdout); scanf("%d %d %d", &x0, &y0, &z0); n = x0 + y0 + z0; fo(i, 1, n) { scanf("%d %d %d", &x[i], &y[i], &z[i]); link($ z[i] - y[i], i); } d[0] = 0; fd(i, 5e5, -5e5) for(int k = final[$ i]; k; k = next[k]) d[++ d[0]] = to[k]; fo(i, 1, n) x1[i] = x[i]; fo(i, 1, n) x[i] = x1[d[i]]; fo(i, 1, n) x1[i] = y[i]; fo(i, 1, n) y[i] = x1[d[i]]; fo(i, 1, n) x1[i] = z[i]; fo(i, 1, n) z[i] = x1[d[i]]; int mi = 5e5; ll sum = 0; fo(i, 1, z0) { t[$ z[i] - x[i]] ++; mi = min(mi, z[i] - x[i]); sum += z[i] - x[i]; } s1[z0] = sum; fo(i, z0 + 1, n) { if(z[i] - x[i] > mi) { t[$ mi] --; t[$ z[i] - x[i]] ++; sum -= mi; sum += z[i] - x[i]; while(t[$ mi] == 0) mi ++; } s1[i] = sum; } memset(t, 0, sizeof t); mi = 5e5, sum = 0; fd(i, n, n - y0 + 1) { t[$ y[i] - x[i]] ++; mi = min(mi, y[i] - x[i]); sum += y[i] - x[i]; } s2[n - y0 + 1] = sum; fd(i, n - y0, 1) { if(y[i] - x[i] > mi) { t[$ mi] --; t[$ y[i] - x[i]] ++; sum -= mi; sum += y[i] - x[i]; while(t[$ mi] == 0) mi ++; } s2[i] = sum; } sum = 0; fo(i, 1, n) sum += x[i]; ll ans = 0; fo(i, z0, n - y0) ans = max(ans, sum + s1[i] + s2[i + 1]); printf("%lld", ans);}
阅读全文
1 0
- JZOJ 5432. 【NOIP2017提高A组集训10.28】三元组
- 【JZOJ 5432】【NOIP2017提高A组集训10.28】三元组
- jzoj5432【NOIP2017提高A组集训10.28】三元组
- 【JZOJ5432】【NOIP2017提高A组集训10.28】三元组
- 【NOIP2017提高A组集训10.28】三元组
- JZOJ5432. 【NOIP2017提高A组集训10.28】三元组
- 【NOIP2017提高A组集训10.28】三元组
- 【NOIP2017提高A组集训10.28】图
- 【NOIP2017提高A组集训10.28】图
- 【NOIP2017提高A组集训10.21】Dark
- 【NOIP2017提高A组集训10.21】Fantasy
- 【NOIP2017提高A组集训10.21】 总结
- 【NOIP2017提高A组集训10.21】 总结
- 【NOIP2017提高A组集训10.21】Fantasy
- 【NOIP2017提高A组集训10.24】合影
- 【NOIP2017提高A组集训10.22】友谊
- 【NOIP2017提高A组集训10.22】友谊
- 【NOIP2017提高A组集训10.25】吃草
- Python从零开始系列连载(5)——Python的基本运算和表达式(上)
- 51nod 1222 最小公倍数计数 莫比乌斯反演+杜教筛
- ipmitool
- PHP MySQL 基本操作 & Navicat for MySQL
- AJAX基本概念
- 【NOIP2017提高A组集训10.28】三元组
- 【实战】一键呼叫的app项目
- 以实力,致创新 | 机智云荣膺“第五届TopDigital创新奖”双料大奖
- 消息队列之RabbitMQ原理
- 本地Python连接服务器中的Mysql数据库
- 均值模糊 高斯模糊
- JSON基本知识
- linux redhat7配置网络
- 【网站建设】对一些人的谴责