小t是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有這批礦產共有n
n個礦石,從11到n
n逐一編號,每個礦石都有自己的重量wiw
i以及價值viv
i。檢驗礦產的流程是:
給定mm
個區間[li
,ri]
[li
,ri
]選出乙個引數w
w對於乙個區間[li
,ri]
[li
,ri
],計算礦石在這個區間上的檢驗值yiy
i:y
i=∑j
=lir
i1×∑
j=li
rivj
(wj≥
w)yi
=j=
li∑
ri
1×j=
li∑
ri
vj(
wj≥
w)這批礦產的檢驗結果y
y為各個區間的檢驗值之和。若這批礦產的檢驗結果與所給標準值s
s相差太多,就需要再去檢驗另一批礦產。小t不想費時間去檢驗另一批礦產,所以他想通過調整引數w
w的值,讓檢驗結果盡可能的靠近標準值s
s,即使得s−y
s−y的絕對值最小。請你幫忙求出這個最小值。
首先不考慮最小值,設ans
[i]a
ns[i
]表示ww為i
i時最終的y
y值。當w
w的值增大時,顯而易見ans
wans
w時增大的。所以這是乙個單調上公升的序列,即
假定ss
的位置
那麼答案肯定就是選擇w=3
w=3或w
=4w=
4了。如何得到的呢?
很明顯,w=3
w=3就是二分出第乙個ans不超過s的位置
,w=4
w=4就是二分出第乙個ans不少於s的位置
!
然後只要在abs
(ans
[3]−
s)ab
s(an
s[3]
−s)和a
bs(a
ns[4
]−s)
abs(
ans[
4]−s
)中取乙個最小值就可以了。
每次o(n+
m)o(
n+m)
字首和求出ans
ans,再套上二分答案,時間複雜度o((
n+m)
logm
ax(w
))o(
(n+m
)log
max(
w)),其中max
(w)m
ax(w
)定值為106
106。
#include
#include
#include
using
namespace std;
typedef
long
long ll;
const
int n=
200010
;int n,m,l,r,mid,w[n]
,v[n]
,x[n]
,y[n]
;ll s,ans,minn1,minn2,read;
char ch;
ll read()
struct node
sum[n]
;ll ask
(int h)
else
for(
int i=
1;i<=m;i++
) ans+
=(ll)
(sum[y[i]
].s-sum[x[i]-1
].s)
*(ll)
(sum[y[i]
].v-sum[x[i]-1
].v)
;//列舉區間求ans
return ans;
}int
main()
minn1=
ask(l-1)
; l=0;
r=1000000
;while
(l<=r)
minn2=
ask(r+1)
; cout<<
min(
abs(minn1-s)
,abs
(minn2-s));
return0;
}
洛谷P1314 聰明的質監員 二分答案
小t是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1到n 逐一編號,每個礦石都有自己的重量 wi 以及價值vi 檢驗礦產的流程是 1 給定m個區間 li,ri 2 選出乙個引數w 3 對於乙個區間 li,ri 計算礦石在這個區間上的檢驗值yi 這批礦產的檢驗結果y 為各...
洛谷 P1314 聰明的質監員
題目描述 小t 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1到n 逐一編號,每個礦石都有自己的重量 wi 以及價值vi 檢驗礦產的流程是 1 給定m 個區間 li,ri 2 選出乙個引數 w 3 對於乙個區間 li,ri 計算礦石在這個區間上的檢驗值yi 這批礦產的...
洛谷p1314 聰明的質監員
聰明的質監員 題目鏈結 有關演算法 二分答案 但是你只二分答案是不夠的,因為你check會炸,所以還要考慮字首和 首先假裝我們的check已經寫好了,main函式 int main if ls s if ls s printf lld min ans1,ans2 return0 輸入沒有什麼可以說的...