Codeforces 题目传送门 & 洛谷题目传送门

原来 jxd 作业里也有我会做的题 i 了 i 了

首先这种题目的套路就是先考虑对于一个固定的 \(c\),怎样求出得分最高的策略,而类似于这样的问题都考虑贪心求解,手玩几组数据就能发现最优方案是将所有题目按照 \(\dfrac{p_i}{t_i}\) 从大到小排列。简单证明一下,考虑按照 P4437 排列的套路,假设有两道题 \(i,j\) 满足 \(\dfrac{p_i}{t_i}>\dfrac{p_j}{t_j}\),那么将 \(i\) 放在 \(j\) 前面的得分为 \(W_1=p_i(1-\dfrac{ct_i}{T})+p_j(1-\dfrac{c(t_i+t_j)}{T})\),将 \(i\) 放在 \(j\) 后面的得分为 \(W_2=p_j(1-\dfrac{ct_j}{T})+p_i(1-\dfrac{c(t_i+t_j)}{T})\),做差可得 \(\Delta=W_1-W_2=\dfrac{c(p_it_j-p_jt_i)}{T}\),而由 \(\dfrac{p_i}{t_i}>\dfrac{p_j}{t_j}\) 知 \(p_it_j-p_jt_i>0\),故 \(\Delta>0\),也就是说将 \(i\) 放在 \(j\) 前面最优,至于 \(\dfrac{p_i}{t_i}\) 相同的 \(i\),一定有 \(\Delta=0\),也就是说 \(\dfrac{p_i}{t_i}\) 相同的 \(i\) 可以随意交换位置。据说这套路还有个专门名字叫什么 Exchange arguments?不过名字啥的不重要辣,MO 里一般叫它调整法,反正这东西在 OI 和 MO 里都挺有用的就对了(

接下来考虑怎样求答案。首先这个 \(c\) 满足单调性,故考虑二分答案,这是题目中疯狂暗示的,再想不到就有些 sb 了罢(别打我)。考虑检验某个 \(c\) 是否合法,我们显然可以确定每道题可能被完成的最靠前的时间,以及每道题可能被完成的最靠后的时间。具体来说,我们将 \((p_i,t_i)\) 按从大到小顺序排序,记 \(sum_i\) 为对于排好序的 \(t_i\),\(\sum\limits_{j=1}^it_j\) 的值。考虑对于一段极长的区间 \([l,r]\) 满足 \(\forall x,y\in [l,r]\) 都有 \(\dfrac{p_x}{t_x}=\dfrac{p_y}{t_y}\),那么显然对于 \(i\in [l,r]\),问题 \(i\) 可能被完成的最靠前的时间为 \(sum_{l-1}+t_i\),最靠后的时间为 \(sum_r\)。因此我们只需检验是否 \(\exist i,j\) 满足 \(p_i>p_j\),完成 \(i\) 最少可能的得分 \(<\) 完成 \(j\) 最大可能的得分,这个可以通过再将所有题目按 \(p_i\) 排序并用 two pointers 维护 \(mx=\max\limits_{p_j<p_i}p_j(1-\dfrac{c·mxt_j}{T})\),其中 \(mxt_j\) 即为上文中所说的问题 \(i\) 可能的最靠后的完成时间。并与 \(i\) 在可能的最靠前的完成时间的得分比较即可。

时间复杂度 \(\mathcal O(n\log n)\)。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1.5e5;
const double EPS=1e-9;
int n;ll T,sum[MAXN+5];
struct data{ll p,t,mn,mx;} a[MAXN+5];
bool cmp1(data lhs,data rhs){return lhs.p*rhs.t>rhs.p*lhs.t;}
bool cmp2(data lhs,data rhs){return lhs.p<rhs.p;}
bool check(double x){
double mx=0;
for(int i=1,j=1;i<=n;i++){
while(a[j].p!=a[i].p) chkmax(mx,1.0*a[j].p*(1-x*a[j].mn/T)),j++;
if(1.0*a[i].p*(1-x*a[i].mx/T)<mx) return 0;
} return 1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i].p);
for(int i=1;i<=n;i++) scanf("%lld",&a[i].t),T+=a[i].t;
sort(a+1,a+n+1,cmp1);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].t;
for(int l=1,r;l<=n;l=r+1){
r=l;while(r<n&&a[r].p*a[r+1].t==a[r].t*a[r+1].p) r++;
for(int i=l;i<=r;i++) a[i].mx=sum[r],a[i].mn=sum[l-1]+a[i].t;
} sort(a+1,a+n+1,cmp2);
double l=0,r=1.0,x=-114514.1919810;
while(fabs(r-l)>EPS){
double mid=(l+r)/2.0;
if(check(mid)) x=l=mid;
else r=mid;
} printf("%.10lf\n",x);
return 0;
}

Codeforces 639E - Bear and Paradox(二分+贪心)的更多相关文章

  1. codeforces 613B B. Skills(枚举+二分+贪心)

    题目链接: B. Skills time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  2. CodeForces 377B---Preparing for the Contest(二分+贪心)

    C - Preparing for the Contest Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

  3. Codeforces C Match Points(二分贪心)

    题目描述: Match Points time limit per test 2 seconds memory limit per test 256 mega bytes input standard ...

  4. codeforces 1251D Salary Changing (二分+贪心)

    (点击此处查看原题) 题意分析 一共有s元钱,要用这些钱给n个人发工资,发给每个人的工资si有最少和最多限制 si ∈[li,ri],在发给n个人的总工资小于s的情况下,要求发给n个人中的工资的中位数 ...

  5. Codeforces Round #262 (Div. 2) 二分+贪心

    题目链接 B Little Dima and Equation 题意:给a, b,c 给一个公式,s(x)为x的各个位上的数字和,求有多少个x. 分析:直接枚举x肯定超时,会发现s(x)范围只有只有1 ...

  6. CodeForces 551C - GukiZ hates Boxes - [二分+贪心]

    题目链接:http://codeforces.com/problemset/problem/551/C time limit per test 2 seconds memory limit per t ...

  7. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  8. Codeforces 680D Bear and Tower of Cubes 贪心 DFS

    链接 Codeforces 680D Bear and Tower of Cubes 题意 求一个不超过 \(m\) 的最大体积 \(X\), 每次选一个最大的 \(x\) 使得 \(x^3\) 不超 ...

  9. 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心

    /** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...

随机推荐

  1. 974.和可被K整除的子数组

    题目 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例: 输入:A = [4,5,0,-2,-3,1], K = 5 输出:7 解释: 有 7 个子数组满足其元 ...

  2. 第二次Alpha Scrum Meeting

    本次会议为Alpha阶段第二次Scrum Meeting会议 会议概要 会议时间:2021年4月24日 会议地点:线上会议 会议时长:30min 会议内容简介:本次会议主要由每个人展示自己目前完成的工 ...

  3. 【SDOI2014】数数(补)

    见 AC自动机(补坑了) [SDOI2014] 数数 简要题意:  我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为子串.例如当S={22,333,0233}时 ...

  4. 六步教你如何用PADS进行PCB设计?

    在使用PADS进行PCB设计的过程中,需要对印制板的设计流程以及相关的注意事项进行重点关注,这样才能更好的为工作组中的设计人员提供系统的设计规范,同时也方便设计人员之间进行相互的交流和检查. 02 设 ...

  5. 深入理解xLua基于IL代码注入的热更新原理

    目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...

  6. 手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序

    上一篇:手把手教你学Dapr - 2. 必须知道的概念 注意: 文章中提到的命令行工具即是Windows Terminal/PowerShell/cmd其中的一个,推荐使用Windows Termin ...

  7. Oracle日志 归档模式管理

    一.查看当前归档模式 archive log list; 二.归档/不归档切换 shutdown immediate; -- 或shutdown normal startup mount; alter ...

  8. python的分支结构

    python分支结构 if结构 python的 if 选择分支结构的基础语法如下,需要注意的是判断条件后面是半角的分号,它的作用相当于Java中的小括号 if 判断条件 : 代码块 elif 判断条件 ...

  9. 关于linux7.x系列下的 systemd 的理解

    历史上Linux的启动一直采用init进程,下面的命令用来启动服务. $ sudo /etc/init.d/apache2 start #或者 $ service apache2 start 这种方法 ...

  10. 使用silky脚手架构建微服务应用

    目录 模板简介 构建独立应用的模板Silky.App.Template 构建模块化应用的模板Silky.Module.Template 开源地址 在线文档 模板简介 使用 dotnet new 命令可 ...