将题意转换为一开始\(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题题解的更多相关文章

  1. 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)\).这就相当于 ...

  2. HHKB Programming Contest 2020 D - Squares 题解(思维)

    题目链接 题目大意 给你一个边长为n的正方形和边长为a和b的正方形,要求把边长为a和b的正方形放在长度为n的正方形内,且没有覆盖(可以相邻)求有多少种放法(mod 1e9+7) 题目思路 这个思路不是 ...

  3. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...

  4. M-SOLUTIONS Programming Contest 2020 题解

    M-SOLUTIONS Programming Contest 2020 题解 目录 M-SOLUTIONS Programming Contest 2020 题解 A - Kyu in AtCode ...

  5. 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 ...

  6. Yahoo Programming Contest 2019 补题记录(DEF)

    D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...

  7. 2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解

    F. Monkeying Around   维护点在多少个线段上 http://codeforces.com/gym/101350/problem/F 题意:有m个笑话,每个笑话的区间是[L, R], ...

  8. 带权并查集: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 ...

  9. atcoder Keyence Programming Contest 2020 题解

    比赛地址 A 题意:给一个\(n*m\)的初始为白色的矩阵,一次操作可以将一行或一列染成 黑色,问至少染出\(k\)个黑点的最少操作次数. \(n\),\(m\)<=100,\(k\)<= ...

随机推荐

  1. 92. Reverse Linked List II 翻转链表II

    Reverse a linked list from position m to n. Do it in one-pass. Note: 1 ≤ m ≤ n ≤ length of list. Exa ...

  2. mds的cpu占用问题分析以及解决办法

    前言 mds是ceph里面处理文件接口的组件,一旦使用文件系统,不可避免的会出现一种场景就是目录很多,目录里面的文件很多,而mds是一个单进程的组件,现在虽然有了muti mds,但稳定的使用的大部分 ...

  3. SSTI Flask

    1.什么是SSTI?什么是Flask? ​ SSTI称为服务端模板注入,主要为Python.Java.PHP的框架在使用渲染函数时,由于代码不规范或者对于用户输入过于信任而导致产生了SSTI.类似于S ...

  4. css中渐变的分割线和自定义滚动条样式

    css中渐变的分隔线: <div style="background:linear-gradient(to left,#efefef,#b6b6b6,#efefef);height:1 ...

  5. sql常用函数整理

    SQL中包含以下七种类型的函数: 聚合函数:返回汇总值. 转型函数:将一种数据类型转换为另外一种. 日期函数:处理日期和时间. 数学函数:执行算术运算. 字符串函数:对字符串.二进制数据或表达式执行操 ...

  6. 宝塔Linux面板基础命令

    安装宝塔Centos安装脚本 yum install -y wget && wget -O install.sh http://download.bt.cn/install/insta ...

  7. Django踩坑记录1

    from django.db import models # Create your models here. class Event(models.Model): name = models.Cha ...

  8. LeetCode周赛#212

    1631. 最小体力消耗路径 #并查集 #最短路径 题目链接 题意 给定一二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 \((row ...

  9. 课时一:JS操作数据

    课时一:JS操作数据 JSAPI请求头 xmlhttp.setRequestHeader("Content-Type", "application/json; chars ...

  10. JAVA在最新版Windows10_1909版本环境下的环境变量配置

    1.配置 1.1新建 JAVA_HOME C:\Program Files\Java\jdk-13.0.2 1.2新建 CLASSPATH .;%JAVA_HOME%\bin;%JAVA_HOME%\ ...