1. 程式人生 > 其它 >聰明的質監員(字首和,二分)

聰明的質監員(字首和,二分)

技術標籤:演算法二分字首和&&差分演算法動態規劃數學建模

聰明的質監員

題目連結
小 T 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1 到 n 逐一編號,每個礦石都有自己的重量 wi 以及價值 vi。
檢驗礦產的流程是:
1、給定 m 個區間[Li,Ri]; 
2、選出一個引數 W; 
3、對於一個區間[Li,Ri],計算礦石在這個區間上的檢驗值 Yi : 
在這裡插入圖片描述
這批礦產的檢驗結果 Y 為各個區間的檢驗值之和。
即:Y = Y1+Y2+…+Ym
若這批礦產的檢驗結果與所給標準值 S 相差太多,就需要再去檢驗另一批礦產。
小 T 不想費時間去檢驗另一批礦產,所以他想通過調整引數 W 的值,讓檢驗結果儘可能的靠近標準值 S,即使得 S-Y 的絕對值最小。

請你幫忙求出這個最小值。

輸入格式

第一行包含三個整數 n,m,S,分別表示礦石的個數、區間的個數和標準值。 
接下來的 n 行,每行 2 個整數,中間用空格隔開,第 i+1 行表示 i 號礦石的重量 wi 和價值 vi 。 
接下來的 m 行,表示區間,每行 2 個整數,中間用空格隔開,第 i+n+1 行表示區間[Li, Ri]的兩個端點 Li 和 Ri。
注意:不同區間可能重合或相互重疊。

輸出格式

輸出一個整數,表示所求的最小值。

資料範圍

1≤n,m≤200000,
0<wi,vi≤106,
0<S≤1012,
1≤Li≤Ri≤n

輸入樣例:

5 3 15
1 5
2 5
3 5
4 5
5 5

1 5
2 4
3 3

輸出樣例:

10

演算法分析

資料為1e6我們需要二分尋找S值,二分的判斷就是Y值.題目是不滿足引數W的時候需要加上加上該點而且需要計數加一,最後算出答案.還有最後一點我們最後二分出的答案不一定是最後的答案,我們尋找的是絕對值最小,所以需要判斷二分出的點後後面一個點

程式碼實現

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll n,m,s;
int L[maxn],R[maxn]; int v[maxn],w[maxn]; ll sum[maxn],cnt[maxn]; ll check(int x) { for(int i=1;i<=n;i++) { if(w[i]>=x) { sum[i]=sum[i-1]+v[i]; cnt[i]=cnt[i-1]+1; } else { sum[i]=sum[i-1]; cnt[i]=cnt[i-1]; } } ll res=0; for(int i=1;i<=m;i++) res+=(sum[R[i]]-sum[L[i]-1])*(cnt[R[i]]-cnt[L[i]-1]); return res; } int main() { cin>>n>>m>>s; for(int i=1;i<=n;i++) { cin>>w[i]>>v[i]; } for(int i=1;i<=m;i++) { cin>>L[i]>>R[i]; } int l=0,r=1e6; while(l<r) { int mid=l+r+1>>1; if(check(mid)>=s) l=mid; else r=mid-1; } ll ans=min(check(l)-s,s-check(l+1)); cout<<ans<<endl; }