AcWing 499. 聪明的质监员(二分+前缀和)

在这里插入图片描述
输入样例:

5 3 15 
1 5 
2 5 
3 5 
4 5 
5 5 
1 5 
2 4 
3 3 

输出样例:

10

这道题说实话并不是很难,我刚开始也是想到了二分,但是那个式子确实让我看的一脸懵逼
后来在老师的代码中才知道,Yi是在Li,Ri区间中求符合wi>=W的个数*符合wi>=W的总价值。求Y与S的最小绝对值。
思路就比较好求了,类似于求lower_bound的二分,可以求>=S的最大W,也可以求<=S的最小W
然后S两边都有可能是绝对值最小,思路就出来了

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int wi[N],vi[N],li[N],Ri[N],cot[N];
int n,m;
LL s[N],S;
LL check(int W)
{
    
    
    for(int i=1;i<=n;i++)
    if(wi[i]>=W)
    {
    
    
        s[i]=s[i-1]+vi[i];
        cot[i]=cot[i-1]+1;
    }
    else
    {
    
    
        s[i]=s[i-1];
        cot[i]=cot[i-1];
    }
    LL res=0;
    for(int i=1;i<=m;i++) res+=(cot[Ri[i]]-cot[li[i]-1])*(s[Ri[i]]-s[li[i]-1]);
    //求在W下的Y
    return res;
}
int main(void)
{
    
    

    cin>>n>>m>>S;
    for(int i=1;i<=n;i++) cin>>wi[i]>>vi[i];
    for(int i=1;i<=m;i++) cin>>li[i]>>Ri[i];
    int l=0,r=1e6+10;
    while(l<r)
    {
    
    
        int mid=l+r>>1;
        if(check(mid)<=S) r=mid;
        else l=mid+1;
    }
    cout<<min(abs(check(r)-S),abs(S-check(r-1)));
}

猜你喜欢

转载自blog.csdn.net/qq_52358098/article/details/113673586
今日推荐