华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 908|回复: 1
打印 上一主题 下一主题

P1314 聪明的质监员

[复制链接]

50

主题

215

帖子

619

积分

高级会员

Rank: 4

积分
619
跳转到指定楼层
楼主
发表于 2018-10-6 18:02:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P1314


题目描述
小T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 w_i以及价值v_i。检验矿产的流程是:
1 、给定m个区间[L_i,R_i]
2 、选出一个参数 W
3、对于一个区间[L_i,R_i],计算矿石在这个区间上的检验值Y_i
这批矿产的检验结果Y 为各个区间的检验值之和。即:Y_1+Y_2...+Y_m
若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产。小T不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近标准值S,即使得S-Y 的绝对值最小。请你帮忙求出这个最小值。

输入输出格式
输入格式:
第一行包含三个整数n,m,S,分别表示矿石的个数、区间的个数和标准值。

接下来的n行,每行2个整数,中间用空格隔开,第i+1行表示ii号矿石的重量w_i和价值v_i
接下来的m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n 行表示区间[L_i,R_i]的两个端点Li和Ri。注意:不同区间可能重合或相互重叠。

输出格式:
一个整数,表示所求的最小值。

输入输出样例
输入样例#1:
5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3
输出样例#1:
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 < w_i,v_i≤10^6,0 < S≤10^12,1 ≤L ≤R ≤n
回复

使用道具 举报

50

主题

215

帖子

619

积分

高级会员

Rank: 4

积分
619
沙发
 楼主| 发表于 2018-10-6 18:02:35 | 只看该作者
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #define FOR(i,a,b) for(register int i=a;i<=b;i++)
  5. #define ROF(i,a,b) for(register int i=a;i>=b;i--)
  6. using namespace std;
  7. const int N=200005;
  8. long long int n,m,S,sum[N],sumn[N],w[N],v[N],ans=0x7fffffffff,minw=0x7fffffff,maxw=-1,an,k,l[N],r[N];
  9. inline long long int abs(long long int x,long long int y){if(x>y)return x-y;else return y-x;}
  10. bool check(int x)
  11. {
  12.     k=0;an=0;
  13.     memset(sum,0,sizeof(sum));
  14.     memset(sumn,0,sizeof(sumn));
  15.     FOR(i,1,n)
  16.     {
  17.         sum[i]=sum[i-1];sumn[i]=sumn[i-1];
  18.         if(w[i]>=x){sum[i]+=v[i];sumn[i]+=1;}
  19.     }
  20.     FOR(i,1,m)k+=(sum[r[i]]-sum[l[i]-1])*(sumn[r[i]]-sumn[l[i]-1]);
  21.     an=abs(S,k);
  22.     if(S>k)return true;
  23.     else return false;
  24. }
  25. int main()
  26. {
  27.     cin>>n>>m>>S;
  28.     FOR(i,1,n){cin>>w[i]>>v[i];minw=min(minw,w[i]);maxw=max(maxw,w[i]);}
  29.     FOR(i,1,m)cin>>l[i]>>r[i];
  30.     long long int L=minw-1,R=maxw+2,mid;
  31.     while(L<=R)
  32.     {
  33.         mid=L+((R-L)>>1);
  34.         if(check(mid))R=mid-1;
  35.         else L=mid+1;
  36.         if(an<ans)ans=an;
  37.     }
  38.     cout<<ans<<endl;
  39.     return 0;
  40. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 02:36 , Processed in 0.097142 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表