luogu 1314 聪明的质检员

二分答案的边界问题还是要注意

double挨着,int+1-1,

此题用到long long,所以初始化ans要足够大,前缀和优化

依然根据check答案大小左右mid,虽然有s,但是有了+1-1加持所以能够自动推出

#include<bits/stdc++.h>
#define int long long
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;

const int N=2e6+50;
int n,m,s,mi,mx,ans,w[N],v[N],l[N],r[N];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}

inline int aabs(int x){return x>0?x:-x;}

int sum[N],cnt[N];

bool check(int mid){int y=0;
    memset(sum,0,sizeof sum);
    memset(cnt,0,sizeof cnt);
    
    rep(i,1,n){
        sum[i]=sum[i-1],cnt[i]=cnt[i-1];
        if(w[i]>=mid)
           sum[i]+=v[i],cnt[i]++;    
    }rep(i,1,m)
        y+=(cnt[r[i]]-cnt[l[i]-1])*(sum[r[i]]-sum[l[i]-1]);
    ans=min(ans,aabs(y-s));
    if(y>s) return 1;
    else return 0;
}

signed main(){
    n=read(),m=read(),s=read();ans=mi=999999999999999999;
    rep(i,1,n) w[i]=read(),v[i]=read(),mi=min(mi,w[i]),mx=max(mx,w[i]);
    rep(i,1,m) l[i]=read(),r[i]=read();
    int l=mi,r=mx;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        bool FG=check(mid);
        
        if(FG) l=mid+1;
        else r=mid-1;
    }
    printf("%lld\n",ans);return 0;
}

怀挺

posted @ 2018-10-02 17:30  ASDIC减除  阅读(145)  评论(0编辑  收藏  举报