Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解
将题意转换为一开始\(t = 0\),第\(i\)个操作是令\(t \leftarrow (a_i + 1) t + (a_i + b_i + 1)\)。记\(A_i = a_i + 1, B_i = a_i + b_i + 1\)。问经过最多经过多少次操作后才能使得进行完这些操作后\(t \leq T\)仍然满足。
我们先推一个贪心性质:
若先进行\(i\)操作,再进行\(j\)操作时满足条件,且\(\frac{A_i - 1}{B_i} < \frac{A_j - 1}{B_j}\),则可以交换\(i\),\(j\)操作的顺序,使得条件仍然满足。
证明:由单调性,只需证明先进行\(i\)操作再进行\(j\)操作后的\(t\)的值大于先进行\(j\)操作再进行\(i\)操作后\(t\)的值。假设一开始的数值为\(t\),则第一种操作组合后,数值为\(A_iA_jt + A_jB_i + B_j\),第二种操作组合后数值为\(A_iA_jt + A_iB_j + B_i\)。
由于\(A_jB_i + B_j > A_iB_j + B_i\)等价于\(\frac{A_i - 1}{B_i} < \frac{A_j - 1}{B_j}\),故结论成立!
因此我们可以将这些操作按\(\frac{A_i - 1}{B_i}\)从大到小排序,然后设计一个DP。设\(f_{i, j}\)表示进行了前\(i\)种操作的\(j\)次后\(t\)的值最小是多少。我们可以得到一个\(O(n^2)\)做法。注意到我们必定先进行\(A_i > 0\)的操作,而这样的操作最多进行\(O(\log T)\)次。再进行\(A_i = 0\)的操作时,必定是按照\(B_i\)从小到大顺序进行。所以我们只需把\(A_i > 0\)的操作拿来\(DP\),并且第二维只考虑到\(O(\log T)\)即可获得一个\(O(n (\log n + \log T))\)时间的算法。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 200005, M = 40;
template <class T>
void read (T &x) {
int sgn = 1;
char ch;
x = 0;
for (ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar()) ;
if (ch == '-') ch = getchar(), sgn = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
x *= sgn;
}
template <class T>
void write (T x) {
if (x < 0) putchar('-'), write(-x);
else if (x < 10) putchar(x + '0');
else write(x / 10), putchar(x % 10 + '0');
}
int n, cnt1 = 0, cnt2 = 0;
long long a[N], b[N], f[N][M + 1], t;
struct node {
long long A;
long long B;
bool operator < (node rhs) const {
long long val1 = (A - 1) * rhs.B;
long long val2 = (rhs.A - 1) * B;
return (val1 > val2) || (val1 == val2 && A < rhs.A);
}
} vec[N];
long long num[N], pre[N];
int main () {
read(n), read(t);
for (int i = 1; i <= n; i++) {
read(a[i]), read(b[i]);
if (a[i]) {
node x = {a[i] + 1, a[i] + b[i] + 1};
vec[++cnt1] = x;
}
else num[++cnt2] = b[i] + 1;
}
sort(vec + 1, vec + cnt1 + 1);
sort(num + 1, num + cnt2 + 1);
pre[0] = 0ll;
for (int i = 1; i <= cnt2; i++) pre[i] = pre[i - 1] + num[i];
for (int i = 0; i <= M; i++) f[0][i] = t + 1;
f[0][0] = 0ll;
for (int i = 1; i <= cnt1; i++) {
for (int j = 0; j <= M; j++) {
f[i][j] = f[i - 1][j];
if (j) f[i][j] = min(f[i][j], vec[i].A * f[i - 1][j - 1] + vec[i].B);
}
}
int ans = 0;
for (int i = 0; i <= M; i++) {
if (f[cnt1][i] > t) continue;
int pos = lower_bound(pre, pre + cnt2 + 1, t + 1 - f[cnt1][i]) - pre - 1;
ans = max(ans, pos + i);
}
write(ans), putchar('\n');
return 0;
}
Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解的更多相关文章
- Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 C题题解
首先,我们将题目理解成若\(i\)与\(j\)距离恰好为\(3\),则不可能\(p_i \equiv p_j \equiv 1 \space or \space 2 (\bmod 3)\).这就相当于 ...
- HHKB Programming Contest 2020 D - Squares 题解(思维)
题目链接 题目大意 给你一个边长为n的正方形和边长为a和b的正方形,要求把边长为a和b的正方形放在长度为n的正方形内,且没有覆盖(可以相邻)求有多少种放法(mod 1e9+7) 题目思路 这个思路不是 ...
- (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)
layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...
- M-SOLUTIONS Programming Contest 2020 题解
M-SOLUTIONS Programming Contest 2020 题解 目录 M-SOLUTIONS Programming Contest 2020 题解 A - Kyu in AtCode ...
- 2021.7.27--Benelux Algorithm Programming Contest 2020 补提
I Jigsaw 题目内容: 链接:https://ac.nowcoder.com/acm/contest/18454/I 来源:牛客网 You have found an old jigsaw pu ...
- Yahoo Programming Contest 2019 补题记录(DEF)
D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...
- 2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解
F. Monkeying Around 维护点在多少个线段上 http://codeforces.com/gym/101350/problem/F 题意:有m个笑话,每个笑话的区间是[L, R], ...
- 带权并查集:CF-2015 ACM Arabella Collegiate Programming Contest(F题)
F. Palindrome Problem Description A string is palindrome if it can be read the same way in either di ...
- atcoder Keyence Programming Contest 2020 题解
比赛地址 A 题意:给一个\(n*m\)的初始为白色的矩阵,一次操作可以将一行或一列染成 黑色,问至少染出\(k\)个黑点的最少操作次数. \(n\),\(m\)<=100,\(k\)<= ...
随机推荐
- ixgbe 驱动 为xxx驱动做准备1
网卡都是pci设备,因此这里每个网卡驱动其实就是一个pci驱动.并且intel这里是把好几个万兆网卡(82599/82598/x540)的驱动做在一起的.V4L2 一样几个类型摄像头合并在一起 先说一 ...
- MySQL视图详细介绍
前言: 在MySQL中,视图可能是我们最常用的数据库对象之一了.那么你知道视图和表的区别吗?你知道创建及使用视图要注意哪些点吗?可能很多人对视图只是一知半解,想详细了解视图的同学看过来哟,本篇文章会详 ...
- 关于vm.min_free_kbytes的合理设置推测
前言 之前系统出现过几次hung住的情况,没有oom,也没有其它内存相关的信息,而linux设计就是去尽量吃满内存,然后再回收清理的机制 探讨 目前这个参数还没有找到合适的处理这个预留的参数,一般也没 ...
- arm-linux校时和时钟同步
# 将时间写到系统 date 2020.08.25-14:02:00 # 将时间同步到硬件时钟芯片 hwclock -f /dev/rtc1 -w # 将时间从硬件时钟芯片同步到系统 hwclock ...
- addslashes()
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串. 作用:防止sql注入
- 「LOJ #6500」「雅礼集训 2018 Day2」操作
description LOJ 6500 solution 根据常有套路,容易想到将区间差分转化为异或数组上的单点修改,即令\(b_i=a_i \ xor\ a_{i-1}\), 那么将\([l,l+ ...
- css3系列之transform 详解scale
scale() scaleX() scaleY() scaleZ() scale3d() 改变的不是元素的宽高,而是 X 和 Y 轴的刻度 本章有个很冷门的知识点 → scale 和 rotate 一 ...
- Lambda表达式(一)入门认识篇
Lambda表达式(一)入门认识篇 Lambda简介 Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极 ...
- layui $().click() 失效问题
//使用此点击事件失效 $(".sub2").on('click', function() { alert('响应点击事件'); }); //将指定的事件绑定在document上, ...
- appium元素定位工具
appium元素定位工具介绍 使用uiautomatorviewer定位工具 使用Appium Inspector定位工具 使用uiautomatorviewer定位工具 谷歌在Android S ...