首页 > 代码库 > [NOIP2011] 聪明的质监员
[NOIP2011] 聪明的质监员
631. [NOIP2011] 聪明的质监员
★★ 输入文件:qc.in
输出文件:qc.out
简单对比
时间限制:1 s 内存限制:128 MB
【问题描述】
小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有自己的重量wi以及价值vi。检验矿产的流程是:
1. 给定 m个区间[Li,Ri];
2. 选出一个参数W;
3. 对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi:
这批矿产的检验结果Y为各个区间的检验值之和。即:
- 若这批矿产的
检验结果
- 与所给标准值 S 相差太多,就需要再去检验另一批矿产。小 T 不想费时间去检验另一批矿产,所以他想通过调整参数 W 的值,让
检验结果
- 尽可能的靠近标准值 S,即使得
S?Y的绝对值最小。请你帮忙求出这个最小值。
【输入】
输入文件 qc.in。
第一行包含三个整数n,m,S,分别表示矿石的个数、区间的个数和标准值。
接下来的n 行,每行2 个整数,中间用空格隔开,第i+1 行表示i 号矿石的重量wi 和价值vi 。
接下来的m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n+1 行表示区间[Li,Ri]的两个端点Li 和Ri。注意:不同区间可能重合或相互重叠。
【输出】
输出文件名为qc.out。
输出只有一行,包含一个整数,表示所求的最小值。
【输入输出样例】
qc.in
5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3
qc.out
10
【输入输出样例说明】
当W 选4 的时候,三个区间上检验值分别为20、5、0,这批矿产的检验结果为25,此时与标准值S 相差最小为10。
【数据范围】
对于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。
solution:
这题真的没啥说的二分w即可,直接上代码吧
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define int long long 7 int read() { 8 int s=0,f=1; 9 char ch=getchar(); 10 while(ch>‘9‘||ch<‘0‘) { 11 if(ch==‘-‘) { 12 f=-1; 13 } 14 ch=getchar(); 15 } 16 while(ch>=‘0‘&&ch<=‘9‘) { 17 s=(s<<1)+(s<<3)+(ch^48); 18 ch=getchar(); 19 } 20 return s*f; 21 } 22 int w[200005],v[200005],n,m,S,mx,mn; 23 int l[200005],r[200005],num[200005],sum[200005]; 24 int sum2[200005],num2[200005]; 25 int Main(){ 26 freopen("qc.in","r",stdin); 27 freopen("qc.out","w",stdout); 28 n=read(); 29 m=read(); 30 S=read(); 31 for(int i=1; i<=n; i++) { 32 w[i]=read(); 33 v[i]=read(); 34 mx=max(mx,w[i]); 35 } 36 for(int i=1; i<=m; i++) { 37 l[i]=read(); 38 r[i]=read(); 39 } 40 long long ans=0x7fffffff; 41 ans<<=5; 42 while(mn<mx) { 43 memset(num,0,sizeof(num)); 44 memset(sum,0,sizeof(sum)); 45 int mid=(mn+mx)>>1,ji=0; 46 for(int i=1; i<=n; i++) { 47 if(w[i]>=mid+1) { 48 num[i]=num[i-1]+1; 49 sum[i]=sum[i-1]+v[i]; 50 } else { 51 num[i]=num[i-1]; 52 sum[i]=sum[i-1]; 53 } 54 } 55 for(int i=1; i<=m; i++) { 56 ji+=(num[r[i]]-num[l[i]-1])*(sum[r[i]]-sum[l[i]-1]); 57 } 58 if(ji==S) { 59 cout<<"0"; 60 return 0; 61 } 62 if(ji>S) { 63 mn=mid+1; 64 } 65 if(ji<S) { 66 mx=mid; 67 } 68 ans=min(ans,abs(S-ji)); 69 } 70 cout<<ans; 71 return 0; 72 } 73 int hehe=Main(); 74 signed main() { 75 ; 76 }
[NOIP2011] 聪明的质监员