华师一附中OI组
标题:
P1314 聪明的质监员
[打印本页]
作者:
倚窗倾听风吹雨
时间:
2018-10-6 18:02
标题:
P1314 聪明的质监员
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
作者:
倚窗倾听风吹雨
时间:
2018-10-6 18:02
#include<iostream>
#include<cstring>
#include<cstdio>
#define FOR(i,a,b) for(register int i=a;i<=b;i++)
#define ROF(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
const int N=200005;
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];
inline long long int abs(long long int x,long long int y){if(x>y)return x-y;else return y-x;}
bool check(int x)
{
k=0;an=0;
memset(sum,0,sizeof(sum));
memset(sumn,0,sizeof(sumn));
FOR(i,1,n)
{
sum[i]=sum[i-1];sumn[i]=sumn[i-1];
if(w[i]>=x){sum[i]+=v[i];sumn[i]+=1;}
}
FOR(i,1,m)k+=(sum[r[i]]-sum[l[i]-1])*(sumn[r[i]]-sumn[l[i]-1]);
an=abs(S,k);
if(S>k)return true;
else return false;
}
int main()
{
cin>>n>>m>>S;
FOR(i,1,n){cin>>w[i]>>v[i];minw=min(minw,w[i]);maxw=max(maxw,w[i]);}
FOR(i,1,m)cin>>l[i]>>r[i];
long long int L=minw-1,R=maxw+2,mid;
while(L<=R)
{
mid=L+((R-L)>>1);
if(check(mid))R=mid-1;
else L=mid+1;
if(an<ans)ans=an;
}
cout<<ans<<endl;
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2