题意:有n个人,每个人有一件衣服需要洗,可以自己手洗花费t时间,也可以用洗衣机洗,但是洗衣机只有一台,即每个时刻最多只能有·一个人用洗衣机洗衣服。现在给你每个人最早可以开始洗衣服的时间,问当洗衣机的洗衣时间分别为1, 2....t的时候洗完所有衣服的最短时间。

思路:首先容易想到我们先把所有人按照洗衣服的时间排序。我们发现,最终洗衣服时间的瓶颈肯定在于后面的人,所以我们考虑怎么使用洗衣机使得总的洗衣时间最短。首先最后一个人是一定要用洗衣机洗衣服的,因为洗衣机的洗衣服时间 <= t, 那么最后一个人用洗衣机洗衣服不会让总时间变长,只可能变短。同理,如果最后一个人用洗衣机和倒数第二个人不冲突的话,倒数第二个人肯定也用洗衣机了。如果倒数第二个人用不了洗衣机,那么前面的人也没必要用洗衣机了,因为倒数第二个人的洗衣时间肯定大于等于前面的人,最后时间的瓶颈只可能在倒数第二个人身上或者倒数第一个人身上了。以此类推,我们可以发现。最后用洗衣机的人的序列肯定是原序列的一个后缀。那么,对于当前的x,怎么确定哪些人用洗衣机呢?设b[i]为第i个人开始洗衣服的时间,假设是从第i个人开始用洗衣机洗衣服,时间限制可能是两种:1:来自第i - 1个人手洗的时间限制:b[i - 1] + t。2:后面的人用洗衣机的时间的结束时间。这个结束时间怎么算呢?我们假设从第i个人开始用洗衣机,最理想情况是他一用完洗衣机别人就可以用,那么时间是b[i] + (n - i + 1) * x, 我们把i及其以后的所有人的理想状态时间都算出来,取最大值就是实际的结束时间。那么我们发现从i开始的人用洗衣机的时间是max(b[i - 1] + t, max(b[k] + (n - k + 1) * x)) (k >= i)。容易发现,b[k] + t是个单调递增的函数, max(b[k] + (n - k + 1) * x)是个单调递减的函数,他们俩取max是一个单谷函数,最优解就是谷底。这个好像不是严格单调函数不能三分,只能暴力枚举。那么对于一个特定的x时间复杂度是O(n)的。但是现在有n个x,怎么办?我们发现,当x等于t的时候,谷底一定在最后面,随着x的不断变小,谷底会逐渐往前移动,那么我们可以用一个指针来指向谷底,每当x减一的时候判断一下谷底是不是前移了,如果是就往前移动。那么新的问题出现了,b[i - 1] + t是常数不用维护,x减一之后max(b[k] + (n - k + 1) * x))好像得全部重新计算了?如果把n - k + 1看成斜率,b[k]看成截距,那么问题就转化为了在一堆直线中当横坐标确定时找纵坐标的最大值,这个用李超线段树可以在O(log(n))的时间内做到。

代码:

#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 1000010;
struct line {
double k, b;
};
line a[maxn];
int tot;
struct node {
int id;
};
node tr[maxn * 4];
double get_pos(int x, int y) {
return a[x].k * y + a[x].b;
}
double cross(int x, int y) {
return (a[x].b - a[y].b) / (a[y].k - a[x].k);
}
void init(int o, int l, int r) {
tr[o].id = 0;
if(l == r) return;
int mid = (l + r) >> 1;
init(ls, l, mid);
init(rs, mid + 1, r);
}
void update(int o, int l, int r, int now) {
if(!tr[o].id) {
tr[o].id = now;
return;
}
int x = tr[o].id;
double l1 = get_pos(now, l), r1 = get_pos(now, r);
double l2 = get_pos(x, l), r2 = get_pos(x, r);
if(l1 <= l2 && r1 <= r2) {
return;
}
else if(l1 > l2 && r1 > r2) {
tr[o].id = now;
return;
}
int mid = (l + r) >> 1;
double y = cross(now, x);
if(y <= mid) update(ls, l, mid, r1 > r2 ? x : now);
else update(rs, mid + 1, r, l1 > l2 ? x : now);
if((y <= mid && r1 > r2) || (y > mid && l1 > l2))
tr[o].id = now;
}
int query(int o, int l, int r, int pos) {
if(l == r) {
return tr[o].id;
}
int mid = (l + r) >> 1, ans = 0;
if(pos <= mid) ans = query(ls, l, mid, pos);
else ans = query(rs, mid + 1, r, pos);
if(!tr[o].id) return ans;
int x = tr[o].id;
if(get_pos(x, pos) > get_pos(ans, pos)) return x;
else return ans;
}
int b[maxn];
LL res[maxn];
int main() {
int n;
LL t;
while(~scanf("%d%lld", &n, &t)) {
init(1, 1, t);
for (int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
}
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++) {
a[i] = (line){(double)n - i + 1, (double)b[i]};
}
b[0] = -t;
LL tmp, tmp1;
update(1, 1, t, n);
int p = n - 1;
for (int i = t; i >= 1; i--) {
while(1) {
int ans = query(1, 1, t, i);
LL t1 = b[ans] + ((LL)n - ans + 1) * i;
tmp = max(t1, b[p] + t);
if(p == 0) break;
tmp1 = max(max(t1, b[p] + ((LL) n - p + 1) * i), b[p - 1] + t);
if(tmp1 <= tmp) {
update(1, 1, t, p);
p--;
}
else break;
}
res[i] = tmp;
}
for (int i = 1; i < t; i++) {
printf("%lld ", res[i]);
}
printf("%lld\n", res[t]);
}
}

  

2019 ICPC南京网络预选赛 I Washing clothes 李超线段树的更多相关文章

  1. 南京网络赛G-Lpl and Energy【线段树】

    During tea-drinking, princess, amongst other things, asked why has such a good-natured and cute Drag ...

  2. 2019 ICPC南京网络赛 F题 Greedy Sequence(贪心+递推)

    计蒜客题目链接:https://nanti.jisuanke.com/t/41303 题目:给你一个序列a,你可以从其中选取元素,构建n个串,每个串的长度为n,构造的si串要满足以下条件, 1. si ...

  3. 2019 ICPC 南京网络赛 F Greedy Sequence

    You're given a permutation aa of length nn (1 \le n \le 10^51≤n≤105). For each i \in [1,n]i∈[1,n], c ...

  4. 2019 ICPC 南京网络赛 H-Holy Grail

    As the current heir of a wizarding family with a long history,unfortunately, you find yourself force ...

  5. 2019南昌邀请赛网络预选赛 M. Subsequence

    传送门 题意: 给出一个只包含小写字母的串 s 和n 个串t,判断t[i]是否为串 s 的子序列: 如果是,输出"YES",反之,输出"NO": 坑点: 二分一 ...

  6. 2019 ICPC 南昌网络赛

    2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 ...

  7. ACM学习历程—SNNUOJ 1110 传输网络((并查集 && 离线) || (线段树 && 时间戳))(2015陕西省大学生程序设计竞赛D题)

    Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的 ...

  8. 2019 ICPC南京站网络赛 H题 Holy Grail(BF算法最短路)

    计蒜客题目链接:https://nanti.jisuanke.com/t/41305 给定的起点是S,终点是T,反向跑一下就可以了,注意判负环以及每次查询需要添加边 AC代码: #include< ...

  9. 2018ACM/ICPC 焦作网络预选赛-A Magic Mirror

    Jessie has a magic mirror. Every morning she will ask the mirror: 'Mirror mirror tell me, who is the ...

随机推荐

  1. CDN绕过姿势小结

    公司的各业务主站都挂了CDN,总结一波CDN绕过技巧. 什么是CDN CDN的全称是Content Delivery Network,即内容分发网络. 其基本思路是尽可能避开互联网上有可能影响数据传输 ...

  2. 【Algorithm】二分查找(递归实现)

    二分查找(递归实现),Java 代码如下: public class BinarySearch { public static int rank(int key, int[] a) { return ...

  3. 【iOS】tableView:cellForRowAtIndexPath: 方法未调用

    今天遇到这个问题, UITableView 的代理方法 tableView:cellForRowAtIndexPath: - (UITableViewCell *)tableView:(UITable ...

  4. IDEA 控制台输出日志无法grep

    不知从何时开始,我的IDEA控制台无法直接使用Grep插件来过滤输出日志了,这个插件真的挺好用的,不知道是升级后造成的还是我自己设置错误,反正在控制台右键无法打开grep来过滤: 在我开发过程中需要这 ...

  5. solr使用心得

    /**   * @author  zhipeng  * @date 创建时间:2015-10-10 下午12:15:35   * @parameter     * @return    */ publ ...

  6. 使用Minifly打造基于视觉感知的跟踪无人机

    前言:无人机和人工智能现在是非常热门的话题,将两者结合起来是一个比较好的创意,本文介绍一种可行的解决方案来实现基于视觉感知的跟踪无人机.从零开始搭建无人机系统工作量和难度(以及钱)都是非常大的,所以在 ...

  7. 深入理解JVM-类加载器深入解析(3)

    深入理解JVM-类加载器深入解析(3) 获得ClassLoader的途径 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader ...

  8. Spring 源码学习(一)-容器的基础结构

    关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料 展示的代码摘取了一些核心方法,去掉一些默认设置和日志输出,还有大多数错误异常也去掉了,小伙伴想看详细代码 ...

  9. Hadoop 系列(七)—— HDFS Java API

    一. 简介 想要使用 HDFS API,需要导入依赖 hadoop-client.如果是 CDH 版本的 Hadoop,还需要额外指明其仓库地址: <?xml version="1.0 ...

  10. 【简洁易懂】CF372C Watching Fireworks is Fun dp + 单调队列优化 dp优化 ACM codeforces

    题目大意 一条街道有$n$个区域. 从左到右编号为$1$到$n$. 相邻区域之间的距离为$1$. 在节日期间,有$m$次烟花要燃放. 第$i$次烟花燃放区域为$a_i$ ,幸福属性为$b_i$,时间为 ...