聪明的质检员

· · 题解

这很容易想到是一道二分查找题目,但是二分却并不好写(sxy dalao不屑)对于区间的把握是二分的一个重点,不过这个题目不是很难可以当做二分练手的题目

而且这个题是区间求和,区间数目多,暴力枚举,,(老师,我会用for循环了!),所以我们使用的前缀和,sum1数组保存到目前为止符合要求的矿石数,sum2数组表示到目前为止符合要求矿石数的价值和

还要注意些细节,开long long不用多强调了,但是输入输出记得写lld,我就是因为这个盯着屏幕干瞪了十分钟,,

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=200010;
struct re{
    ll left,right;
}section[maxn];
ll n,m,s,v[maxn],w[maxn],i,j,sum1[maxn],sum2[maxn];
ll now;
ll ab(ll c)
{
    return c>0 ? c : -c ;
}
void look_up(ll l,ll r)
{
    if(l==r)return;
    ll mid=(l+r)/2;
    memset(sum1,0,sizeof(sum1));
    memset(sum2,0,sizeof(sum2));
    for(i=1;i<=n;i++)
    {
        sum1[i]=sum1[i-1];
        sum2[i]=sum2[i-1];
        if(w[i]>=mid)
        {
            sum1[i]++;
            sum2[i]+=v[i];
        }
    }
    ll Y=0;
    for(i=1;i<=m;i++)
    {
        Y+=(sum1[ section[i].right ]-sum1[ section[i].left-1 ])*(sum2[ section[i].right ]-sum2[ section[i].left-1 ]);
    }
    if(ab(s-Y)<ab(s-now))now=Y;
    if(s>Y)look_up(l,mid);
    if(s==Y)
    {
        now=s;
        return;
    }
    if(s<Y)look_up(mid+1,r);
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(i=1;i<=n;i++)scanf("%lld%lld",&w[i],&v[i]);
    for(i=1;i<=m;i++)scanf("%lld%lld",§ion[i].left,§ion[i].right);
    look_up(1,100000);
    printf("%lld",ab(s-now));
    return 0;
}