leo101
tags:
- 贪心
date: 2019-4-4
jag2017autumnJ Farm Village
题面
翻译
数轴上有 n 个村庄,每个村庄可以生产两个单位的粮食。在每个村庄生产一单位粮食有一定的代价。运输粮食的代价就是运输的距离。求最小代价使得每个村庄都有 一个单位的粮食。
题解
虽然在叶老的课件里这题是贪心优化费用流,但是讲起来和写起来和费用流没有毛关系
首先先把问题抽象一下,每个村庄可以有两个出口,需要一个入口,自给自足就可以看作是自己出口给自己,然后
根据一般套路准备两个堆,一个出口一个进口。
————叶老
首先预处理一下,把 d 取前缀和,方便计算距离
那么我们先贪心的想(也就是不计之后的代价),把这一次的出口与之前的入口需求相匹配,如果可以优化答案(也就是他们之间的距离 + \(G_i\)比相匹配的节点自给自足更优),那么就直接使用
然后就有反悔操作,就是更加后面的节点的出口,匹配前面我们匹配上的这个节点,所以每当我们根据贪心取完一次后(贪心每次是从入口堆里取最小值与当前的出口相匹配),就再往入口堆里面丢一个\(-(当前给答案的贡献) - dist[i] + g[i]\),方便之后反悔(说实话只有这里有点像网络流)
然后还有一个反悔就是这一次的出口不给之前的,给之后的,那么就往出口堆里丢一个\(-(给答案造成的贡献) - dist[i] + g[i]\),以便之后反悔
做完上述的发现自己的入口需求还没有解决,那么就从出口堆里取出一个最优的,与自己匹配
然后再往入口堆里丢一个\(-(对答案造成的贡献) - dist[j]\)以便之后反悔(用后面的出口来满足自己的入口)
代码
/**************************
* Author : Leo101
* Problem : Farm Village
* Tags : 贪心
**************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <functional>
#define _FILE(s) freopen(#s".in", "r", stdin); freopen(#s".out", "w", stdout)
#define gi get_int()
typedef long long LL;
#define int LL
const int MAXN = 200010;
int get_int()
{
int x = 0, y = 1; char ch = getchar();
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') y = -1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return x * y;
}
int heap1[MAXN], heap2[MAXN], dist[MAXN], cnt1, cnt2;
int topHeap(int* heap, int &cnt)
{
return heap[0];
}
int deleteHeap(int* heap, int &cnt)
{
std :: pop_heap(heap, heap + cnt, std :: greater<int>());
return heap[--cnt];
}
void insertHeap(int* heap, int val, int &cnt)
{
heap[cnt++] = val;
std :: push_heap(heap, heap + cnt, std :: greater<int>());
}
signed main()
{
_FILE(code);
int n = gi, ans = 0;
for (int i = 1; i < n; i++) dist[i] = gi + dist[i - 1];
for (int i = 0; i < n; i++) {
int cost = gi;
for (int j = 0; j < 2; j++) {
int tmp = topHeap(heap1, cnt1) + dist[i] + cost;
if (cnt1 != 0 && tmp < 0) {
deleteHeap(heap1, cnt1); ans += tmp;
insertHeap(heap1, -dist[i] - cost, cnt1);
insertHeap(heap2, -dist[i] + cost - tmp, cnt2);
} else {
insertHeap(heap2, -dist[i] + cost, cnt2);
}
}
int tmp = deleteHeap(heap2, cnt2) + dist[i];
ans += tmp;
insertHeap(heap1, -tmp - dist[i], cnt1);
}
printf("%lld\n", ans);
return 0;
}
leo101的更多相关文章
- Luogu P3757 [CQOI2017]老C的键盘
题目描述 老C的键盘 题解 显然对于每个数 x 都有唯一对应的 \(x/2\) , 然而对于每个数 x 却可以成为 \(x*2\) 和 \(x*2+1\) 的对应数 根据这一特性想到了啥??? 感谢l ...
随机推荐
- Java中synchronized关键字理解
好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...
- git将本地仓库中的文件上传到远程仓库
现在我们开始创建本地git仓库(版本库又叫仓库) (本地仓库:$ git init之后的目录): 1.任意地方新建文件夹aaa,右击git bash here, 2.弹出一个对话框, 3. 首先配置你 ...
- Java集合-07Map接口及其抽象类
简介 前面把List基本记录完了,对于集合List,Map,Set,因为Set基于Map,故先记录Map. 这一篇主要记录Map接口及其抽象类(java version:1.8) 整体架构 参考上图, ...
- Servlet3.x部署描述符
简介 web.xml即部署描述符,位于WEB-INF目录下.在Servlet3以上版本有提供了注解的方式部署Servlet,因此web.xml是可选的.web.xml大概框架如下: <?xml ...
- 中心极限定理(为什么y服从高斯分布)
因为每一条数据都服从IID原则: 根据中心极限定理,当数据增加的时候,样本均值的分布慢慢变成正态分布 不管分布式什么分布,累加起来都是高斯分布 As sum increases, sum of non ...
- Opencv的imread用法
所有参考来自网上仅仅做学习记录用,具体正确性需要在具体项目各自验证,不涉及具体错误代码处理调试等问题,欢迎发现发现问题~ 参考: 1. https://blog.csdn.net/LiheZhu/ar ...
- Tensorflow学习笔记No.6
数据的批标准化 本篇主要讲述什么是标准化,为什么要标准化,以及如何进行标准化(添加BN层). 1.什么是标准化 传统机器学习中标准化也叫做归一化. 一般是将数据映射到指定的范围,用于去除不同维度数据的 ...
- SHOI 2013 【扇形面积并】
早上考的,我打了80分的部分分,出来和同学讨论的时候真想扇自己一巴掌...... 题目描述: 给定 n 个同心的扇形,求有多少面积,被至少k 个扇形所覆盖. 输入输出格式 输入格式: 第一行是三个整数 ...
- [学习笔记] Tarjan算法求强连通分量
今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...
- Java源码详解系列(十一)--Spring的使用和源码
Spring 是一个一站式的 Java 框架,致力于提高我们项目开发的效率.通过 Spring,我们可以避免编写大量额外代码,更专注于我们的核心逻辑.目前,Spring 已经成为最受欢迎的 Java ...