【解題報告】 洛谷P6733 間歇泉
阿新 • • 發佈:2020-10-29
【解題報告】 洛谷P6733 間歇泉
題目描述
有一個間歇泉,冒出了 n 杯水,由於一些原因,每杯水的溫度、體積不同。第 i 杯水的溫度為 ci體積為 ai
現在混合任意兩杯水,每混合兩杯水都會得到一個新的溫度值,求可能得到的第 kkk 高的溫度值(不計熱量損失)。
你的答案建議至少保留小數點後 3 位(與標準答案之差在 \(10^{-2}\) 以內即視為通過)。
輸入格式
第一行一個數 n,k,意義如題述。
接下來 n行,每行兩個數 ai,c
輸出格式
一行一個實數,表示混合後的水的第 kkk 高溫度。
輸入輸出樣例
輸入 #1
5 1
1 5
4 2
5 3
2 3
1 4
輸出 #1
4.500
說明/提示
樣例 1 說明
第 1 和第 5杯水混合,得到 4.5的溫度值。可以發現,這是可能得到的最高水溫。
樣例 2
見題目附件中 pour2.in
與 pour2.ans
。
資料規模與約定
本題採用捆綁測試。
- 子任務 1(9 pts):有 \(1\le n\le 10\)
- 子任務 2(40 pts):保證 \(k=1\)
- 子任務 3(50 pts):無特殊限制。
- 子任務 4(1 pts):Hack 資料。
對於 100% 的資料,有 \(1\le n\le 10^5, 1\le k \le \frac {n(n-1)} {2},1\le a_i,c_i \le 10^9\)
子任務 2/3/4 時限 2s,子任務 1 時限 1s。
前置知識
對於兩杯體積、溫度分別為\((a_i,c_i),(a_j,c_j)\)的水,混合後溫度為:
\[T=\frac {a_i c_i+ a_j c_j} {a_i+c_j} \]思路
二分。
這道題符合我們的求第k大的數的形式,因此我們可以進行二分答案來做題目。
首先分析一下這道題目:
可以混合任意兩杯水來得到溫度值,找第k大的溫度值
設這個第k大的溫度值為v
\[\frac {a_ic_i+a_jc_j} {a_i+c_j}\ge v \]變形可以得到
\[a_ic_i-v a_i\ge va_j-a_jc_j \]問題就是求有多少i,j滿足\(a_i\ge b_j\)
程式碼
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <string> using namespace std; const double eps=0.001; int n,k; int a[100005],c[100005]; double p[100005],q[100005]; long double ans; bool cmp(double a,double b) { return a<b; } bool check(double v) { long long tot=0; for(int i=1;i<=n;i++) { double x=a[i]*1.0*c[i],y=v*a[i]; p[i]=x-y; q[i]=y-x; if(q[i]-p[i]<eps) tot--; } sort(p+1,p+1+n,cmp); sort(q+1,q+1+n,cmp); int j=0; for(int i=1;i<=n;i++) { while(q[j+1]-p[i]<eps&&j+1<=n) j++; tot+=j; } return (tot/2<k); } int main() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]>>c[i]; long double l=1,r=1e9,mid; while(r-l>eps) { mid=(l+r)/2; if(check(mid)) r=mid,ans=mid; else l=mid; } printf("%.3Lf\n",ans); return 0; }