6700. 【2020.06.07省選模擬】得分(score )
(File IO): input:score.in output:score.out
Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits
Description
Input
Output
Sample Input
樣例 1 輸入: 3 4 3 10 1 1 8 樣例 2 輸入: 4 7 20 15 10 7 20 15 10
Sample Output
樣例 1 輸出: 0.62500000000 樣例 2 輸出: 0.31901840491
Data Constraint
Hint
題意:
給你n個二元組(a, t), 二元組的位置可以隨意交換, T是所有t的總和。給出二元組i權值的計算方式bi = ai(1 - cxi/T)。
其中c是係數,xi是在一定的排列順序下,i以及前面所有二元組的t值總和。求出最大的c, 使得 在sigma(bi) 最大的所有情況下,不存在排列中ai < a[j] 但, b[i] > b[j]。
思路:
通過推導,不難發現c的單調性。
於是二分。
發現那個最優排列滿足a/t較大的放在前面,設k = a/t。
證明易。在排列中取兩個位置i,j,討論他們在排列中位置對答案貢獻的區別,即證。
現在好像b已經確定了。
但是, 別忘了,對於k = k‘ , 我們可以在排列中交換兩個二元組的位置。
所以,對於一個二元組,它實際上可能有多個不同的權值。
如圖:
那怎麼辦呢?
考慮check函數。
我們要尋找ai < aj , bi > bj
那麼可以以a爲關鍵字排序,對於當前遍歷到的一個二元組i, 檢查是否前面有bj > bi。
因爲我們要滿足這個c在所有條件下都符合題意,所以,只需要判斷bj max 是否 > bi min即可。
也就是維護一個前綴最大值,還有bimin bimax。
解。
trick:
提交即可。
#include<cstdio>
#include<algorithm>
#define sf scanf
#define mem(a, b) memset(a, b, sizeof(a))
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout);
#define F(i, a, b) for(register ll i = a; i <= b ; i++)
#define Fd(i, a, b) for(register ll i = a; i >= b ; i--)
#define pf printf
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define mod (ll)(1e9 + 7)
#define inf 2147483647
#define ll long long
#define N 200010
using namespace std;
inline ll in() {
ll x=0;
char ch = getchar(); ll f = 0;
while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
x = f ? -x : x;
return x;
}
struct node {
int a, t, minx, maxx;
double minb, maxb;
double key() {return (double)a / t;}
}d[N];
int n, T;
double ans;
bool cmp1 (node a, node b) {return a.key() > b.key();}
bool cmp2 (node a, node b) {return a.a < b.a;}
const double eps = 0.000000001;
int LAS[N], FIR[N];
int check(double c) {
F(i, 1, n) d[i].minb = (double)d[i].a * (1.00 - c * d[i].maxx / T), d[i].maxb = (double)d[i].a * (1.00 - c * d[i].minx / T);
double premax = 0;
F(i, 1, n) {
if(d[i].a == d[i - 1].a) {
i = FIR[i];
continue;
}
if(premax > d[i].minb) return 0;
premax = premax < d[i].maxb ? d[i].maxb : premax;
}
return 1;
}
void binary() {
double l = 0.00, r = 1.00;
while(r - l > eps){
double mid = (l + r) / 2.00;
if(check(mid)) {
ans = mid;
l = mid;
}else r = mid;
}
}
int time[N], las[N], fir[N];
void init() {
F(i, 1, n) time[i] = time[i - 1] + d[i].t;
F(i, 1, n) if(d[i].key() != d[i - 1].key()) fir[i] = i; else fir[i] = fir[i - 1];
Fd(i, n, 1) if(d[i].key() != d[i + 1].key()) las[i] = i; else las[i] = las[i + 1];
F(i, 1, n) d[i].minx = d[fir[i] - 1].maxx + d[i].t, d[i].maxx = time[las[i]];
}
int main() {
open("score");
n = in();
F(i, 1, n) d[i].a = in();
F(i, 1, n) d[i].t = in();
sort(d + 1, d + 1 + n, cmp1);
init();
sort(d + 1, d + 1 + n, cmp2);
T = time[n];
F(i, 1, n) if(d[i].a != d[i - 1].a) LAS[i] = i; else LAS[i] = LAS[i - 1];
Fd(i, n, 1) if(d[i].a != d[i + 1].a) FIR[i] = i; else FIR[i] = FIR[i + 1];
binary();
pf("%.10lf", ans);
return 0;
}