[二分]NOIP2011 day2 T2 聰明的質檢員
阿新 • • 發佈:2019-02-10
聰明的質檢員
From 西部314
背景 Background
NOIP2011 day2 第二題
描述 Description 小T 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1到n 逐一編號,每個礦石都有自己的重量 wi 以及價值vi 。檢驗礦產的流程是:
1 、給定m 個區間[Li ,Ri];
2 、選出一個引數 W;
3 、對於一個區間[Li ,Ri],計算礦石在這個區間上的檢驗值Yi:
Yi=Σ1*Σvj,Σ的迴圈變數為j,這裡j要滿足j∈[Li,Ri]且wj≥W,這裡j是礦石編號。
這批礦產的檢驗結果Y為各個區間的檢驗值之和。ΣYi,Σ的迴圈變數為i,1≤i≤m。
若這批礦產的檢驗結果與所給標準值S 相差太多,就需要再去檢驗另一批礦產。小T不想費時間去檢驗另一批礦產,所以他想通過調整引數W 的值,讓檢驗結果儘可能的靠近標準值S,即使得S-Y 的絕對值最小。請你幫忙求出這個最小值。 輸入格式 Input Format
第一行包含三個整數n ,m,S,分別表示礦石的個數、區間的個數和標準值。 接下來的n 行,每行 2 個整數,中間用空格隔開,第i+1 行表示 i 號礦石的重量 wi 和價值vi 。
接下來的m 行,表示區間,每行2 個整數,中間用空格隔開,第i+n+1 行表示區間[Li, Ri]的兩個端點 Li 和Ri 。注意:不同區間可能重合或相互重疊。 輸出格式 Output Format 輸出只有一行,包含一個整數,表示所求的最小值。 樣例輸入 Sample Input [複製資料]
樣例輸出 Sample Output [複製資料]
時間限制 Time Limitation
各個測試點1s
註釋 Hint 對於10% 的資料,有 1 ≤n ,m≤10;
對於30% 的資料,有 1 ≤n ,m≤500 ;
對於50% 的資料,有 1 ≤n ,m≤5,000;
對於70% 的資料,有 1 ≤n ,m≤10,000 ;
描述 Description 小T 是一名質量監督員,最近負責檢驗一批礦產的質量。這批礦產共有 n 個礦石,從 1到n 逐一編號,每個礦石都有自己的重量 wi 以及價值vi 。檢驗礦產的流程是:
1 、給定m 個區間[Li ,Ri];
2 、選出一個引數 W;
3 、對於一個區間[Li ,Ri],計算礦石在這個區間上的檢驗值Yi:
Yi=Σ1*Σvj,Σ的迴圈變數為j,這裡j要滿足j∈[Li,Ri]且wj≥W,這裡j是礦石編號。
這批礦產的檢驗結果Y為各個區間的檢驗值之和。ΣYi,Σ的迴圈變數為i,1≤i≤m。
若這批礦產的檢驗結果與所給標準值S 相差太多,就需要再去檢驗另一批礦產。小T不想費時間去檢驗另一批礦產,所以他想通過調整引數W 的值,讓檢驗結果儘可能的靠近標準值S,即使得S-Y 的絕對值最小。請你幫忙求出這個最小值。 輸入格式 Input Format
接下來的m 行,表示區間,每行2 個整數,中間用空格隔開,第i+n+1 行表示區間[Li, Ri]的兩個端點 Li 和Ri 。注意:不同區間可能重合或相互重疊。 輸出格式 Output Format 輸出只有一行,包含一個整數,表示所求的最小值。 樣例輸入 Sample Input [複製資料]
註釋 Hint 對於10% 的資料,有 1 ≤n ,m≤10;
對於30% 的資料,有 1 ≤n ,m≤500 ;
對於50% 的資料,有 1 ≤n ,m≤5,000;
對於70% 的資料,有 1 ≤n ,m≤10,000 ;
對於100%的資料,有 1 ≤n ,m≤200,000,0 < wi, vi≤10^6,0 < S≤10^12,1 ≤Li ≤Ri ≤n 。
w為引數
tt[i]表示 1..i個礦中wi>=w的個數 tt[i]=tt[i-1]+1 (滿足wi>=w)
else tt[i]=tt[i-1]
vvw[i] 表示1..i個礦中wi>=w的價值和 ww[i]=ww[i-1]+w[i] (滿足)
else ww[i]=ww[i-1]
對於一個l[i] r[i]的查詢 mark=(tt[r[i]]-tt[l[i]-1])*(ww[r[i]]-ww[l[i]-1])
累加mark 作為 每一個w 答案
顯然 mark單調遞減
二分w即可
二分可以有很多種寫法...
left:=1;right:=max;
while left+1<right do
begin
mid:=(left+right)div 2;
ans:=work(mid);
if ans>s then left:=mid
else right:=mid;
end;
procedure search;
var l,r,mid:longint;
tt,kk:qword;
begin
l:=0;r:=max;ans:=10000000000000;
while l<=r do
begin
mid:=(l+r)shr 1;
tt:=ac(mid);
if tt>s then kk:=tt-s else kk:=s-tt;
if ans>kk then ans:=kk;
if tt<s then r:=mid-1;
if tt>s then l:=mid+1;
if tt=s then exit;
end;
end;
var a,b,n,m,s,ans,left,right,mid,max:int64;
w,l,r,v,tt,vv:array[0..200000]of int64;
i,j:longint;
function min(a,b:int64):int64;
begin
if a>b then exit(b) else exit(a);
end;
function work(ww:int64):int64;
var tot:int64;
j:longint;
begin
tot:=0;
fillchar(tt,sizeof(tt),0);
fillchar(vv,sizeof(vv),0);
for j:=1 to n do
if w[j]>=ww then
begin
tt[j]:=tt[j-1]+1;
vv[j]:=vv[j-1]+v[j];
end else
begin
tt[j]:=tt[j-1];
vv[j]:=vv[j-1];
end;
for j:=1 to m do
tot:=tot+(tt[r[j]]-tt[l[j]-1])*(vv[r[j]]-vv[l[j]-1]);
exit(tot);
end;
begin
readln(n,m,s);
for i:=1 to n do readln(w[i],v[i]);
for i:=1 to m do readln(l[i],r[i]);
max:=0;
for i:=1 to n do if max<w[i] then max:=w[i];
left:=1;right:=max;
while left+1<right do
begin
mid:=(left+right)div 2;
ans:=work(mid);
if ans>s then left:=mid
else right:=mid;
end;
writeln(min(abs(work(right)-s),abs(work(left)-s)));
readln;
end.