6700. 【2020.06.07省選模擬】得分(score )

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;
} 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章