聰明的質監員【題目鏈結】
有關演算法:
二分答案;
但是你只二分答案是不夠的,因為你check會炸,所以還要考慮字首和;
首先假裝我們的check已經寫好了,main函式:
int輸入沒有什麼可以說的,然後是二分答案,二分答案的話,從0~最大的wi;main()
if(ls==s)
if(ls>s)
}printf(
"%lld
",min(ans1,ans2));
return0;
}
二分的標準套路,先計算mid,用check函式判應該往左區間二分還是右區間二分,比較不好想的就是怎麼判斷往左區間還是右區間二分,這裡可以想到,當我們求出的中間值的y之後,如果發現它比s小,那麼如果要找更小的差距,應該讓y的值更大才有可能,那麼如果讓y的值更大,我們應該選入更多的礦產,所以我們應該使二分的答案減小,因此r=mid-1;然後這裡記錄兩個答案,ans1,ans2,分別記錄的是求得的值小於s的最小差,求得值大於s的最小差(顯然等於s時就直接輸出不需要再繼續迴圈了);
然後如果沒有找到使差為0的w,我們就輸出ans1和ans2中較小的乙個;
好了講完了;
並沒有講完啊,我們還莫得講check函式;
最簡單的方法,暴力掃瞄:
ll check(ll x)然後你會發現你t成這樣:y+=(cnt*sum);
}return
y;}
y;}sum[i]表示1~i所有點中所有wi>=二分答案的的礦產的v之和,cnt[i]表示1~i以內所有點中所有wi>=二分答案的礦產個數;
然後處理應該很好理解,不再贅述;
然後再一次for迴圈,對於每個區間,利用維護的字首和計算sum*cnt,然後相加即為答案;
#include#define ll long longend-using
namespace
std;
inline ll read()
ll n,m,w[
200001],v[200001],s,_l[200001],_r[200001],sum[200001],cnt[200001
];ll _abs(ll x)
ll check(ll x)
for(int i=1;i<=m;i++)
returny;}
intmain()
if(ls==s)
if(ls>s)
}printf(
"%lld
",min(ans1,ans2));
return0;
}
洛谷 P1314 聰明的質監員
題目描述 小t 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1到n 逐一編號,每個礦石都有自己的重量 wi 以及價值vi 檢驗礦產的流程是 1 給定m 個區間 li,ri 2 選出乙個引數 w 3 對於乙個區間 li,ri 計算礦石在這個區間上的檢驗值yi 這批礦產的...
洛谷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 這批礦產的檢驗結果y...