原題:
小t 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 nn 個礦石,從 11到nn 逐一編號,每個礦石都有自己的重量wi 以及價值vi。檢驗礦產的流程是:
1 、給m個區間(li-ri)
2 、選出乙個引數 w;
3 、對於乙個區間(li-ri) ,計算礦石在這個區間上的檢驗值yi :
這批礦產的檢驗結果y 為各個區間的檢驗值之和。即:y1+y2+…ym
若這批礦產的檢驗結果與所給標準值ss 相差太多,就需要再去檢驗另一批礦產。小t不想費時間去檢驗另一批礦產,所以他想通過調整引數w 的值,讓檢驗結果盡可能的靠近標準值s,即使得s-y 的絕對值最小。請你幫忙求出這個最小值。
輸入輸出格式
輸入格式:
第一行包含三個整數n,m,s分別表示礦石的個數、區間的個數和標準值。
接下來的n行,每行2個整數,中間用空格隔開,第i+1行表示ii號礦石的重量wi 和價值vi。
接下來的m 行,表示區間,每行2個整數,中間用空格隔開,第i+n+1行表示區間[l_i,r_i]的兩個端點li和ri 。
注意:不同區間可能重合或相互重疊。
輸出格式:
乙個整數,表示所求的最小值。
輸入輸出樣例
輸入樣例#1:
5 3 15
1 52 5
3 54 5
5 51 5
2 43 3
輸出樣例#1:
10說明
【輸入輸出樣例說明】
當w選4的時候,三個區間上檢驗值分別為 20,5 ,0 ,這批礦產的檢驗結果為 25,此時與標準值s相差最小為10。
【資料範圍】
1 ≤n ,m≤200,000,0 < wi,vi≤10^6,0 < s≤10^12,1 ≤li ≤ri ≤n,m≤200,000,0。
題意:有n塊石頭,每乙個都有自己的重量wi和價值vi,現在給出m個區間,給出乙個測評標準w,每乙個區間內都能夠按照題目中的方式求出乙個yi,最後計算所有yi和為y,同時給出乙個標準值s,求怎樣的w才能使y-s最小,輸出最小值。
題解:首先上來的乙個難題就是這個中的計算方式:
兩個求和符號,其實就是先運算後面的求和符號再運算前面的求和符號。而對於這道題目來說,因為所有的上下限都一樣,就相當於求出所有大於w的石頭(假設總數為x)的價值之和,再加上x遍。也就是求出所有大於w的石頭價值之和,並且乘以大於w的石頭數量。
第二個問題就是二分了:
這道題目很明顯要對w來二分,可以確定w的下限就是所有石頭中重量最小的那乙個減1,上限就是所有石頭中重量最大的加二(加二是因為要考慮y=0的情況)。判斷函式只需要利用字首和來優化時間,降低複雜度。
計算出y後與s比較,若是大了,則證明w取小了,反之則取大了。並且每一次都記錄y-s。最終答案為最小的y-s。
注意:每一次判斷是都要對資料初始化(sv陣列,sn陣列,y,sum)。
附上ac**:
#include #include using namespace std;
int n,m,w[2000005],v[2000005],l[200005],r[200005];
long long sv[200005],sn[200005];//字首和sv用來儲存前i個中重量大於w的價值之和,sn用來儲存前i個裡面有幾個的重量大於w
long long s,y,sum;
bool check(int mid)
else
}for(int i=1;i<=m;i++)
sum=y-s;
sum=sum>0?sum:-sum;//取絕對值
if(y>s)return true;
else return false;
}int main()
for(int i=1;i<=m;++i)
long long ans=1e13;
le=le-1,ri=ri+2;//下限為重量中最小值減一,上限為重量中最大值加二,目的是為了能夠包含最小值和最大值加一,
//加二的原因是為了考慮到乙個石頭都沒有取y=0的情況
while(le<=ri)
cout <
return 0;
}
二分 字首和 聰明的質檢員 洛谷P1314
題意 給出n個產品的重量w和價值v,給定m個區間,每個區間通過乙個包含引數w的式子來計算,使總的值逐漸逼近乙個值s 分析 很明顯w為0時,所有產品都滿足,此時y最大,當w比重量w的最大值還大時,所有產品都不滿足,此時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 輸入沒有什麼可以說的...