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\)<= ...
随机推荐
- shell 脚本之set 命令(转)
服务器的开发和管理离不开 Bash 脚本,掌握它需要学习大量的细节. set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.本文介绍它的基本用法,让你可以更安心地使用 ...
- 修改ssh的默认22端口,并使用scp的方法
修改默认的22的ssh端口只需要修改 /etc/ssh/sshd_config 中的 port 字段为你想要的端口就可以了 以后用其他机器ssh登录这台机器只需要: ssh -p (port) (ip ...
- android下vulkan与opengles纹理互通
先放demo源码地址:https://github.com/xxxzhou/aoce 06_mediaplayer 效果图: 主要几个点: 用ffmpeg打开rtmp流. 使用vulkan Compu ...
- 常见的名片尺寸如何在CorelDRAW预设
说到名片想必大家肯定不陌生,是我们生活中随处可见的物品,也是商家宣传必不可少的印刷物料.那么名片的尺寸是多少?我们做名片的时候该如何把握好名片的尺寸呢?在CDR中有专门的名片尺寸,下面小编就为大家简单 ...
- GIF图保存下来不会动?用Folx的浏览器捕获下载功能试试!
表情包大多是GIF格式的动图,有时候使用浏览器的另存为保存完发现并不能动态播放,怎么办呢?试试Folx提供的浏览器捕获下载功能,就能将各种格式的图片,包括GIF动图的下载链接捕获下来,供进一步下载使用 ...
- 【模板】【P3605】【USACO17JAN】Promotion Counting 晋升者计数——动态开点和线段树合并(树状数组/主席树)
(题面来自Luogu) 题目描述 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者! 为了方便,把奶牛从 1⋯N(1≤N≤100,000) 编号,把公司组织成一棵树 ...
- IDEA集成Docker插件后出现日志乱码的解决办法
修改IDEA的vmoptions文件 找到IDEA安装目录的bin目录,在idea.exe.vmoptions和idea64.exe.vmoptions文件中追加以下内容: -Dfile.encodi ...
- wsgi_uwsgi_nginx
1.一些重要概念 https://www.cnblogs.com/xiaonq/p/8932266.html 1.1 web容器 什么是web容器 1.web容器是帮助我们部署java.php.pyt ...
- 生成微博授权URL及回调地址
1.创建apps/oauth模块进行oauth认证 '''2.1 在apps文件夹下新建应用: oauth''' cd syl/apps python ../manage.py startapp oa ...
- Idea 查找加替换 功能
本页查找 快捷键:ctr+F 鼠标框选 所需内容 再加快捷键 查找更加方便 替换功能