[NOIP2011]聪明的质检员

二分答案的大水题。二分一下W,然后记录一下前缀满足wi≤W的个数,前缀满足这个条件的vi的和,check的时候直接O(n+m)的check就行了。

记得开long long

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=200005;
int n,m,sum1[N],w[N],v[N],l[N],r[N];
ll S,sumv[N];
ll ck(int mid) {
    for(int i=1;i<=n;i++) {
        sum1[i]=sum1[i-1]+(w[i]>=mid);
        sumv[i]=sumv[i-1]+(v[i]*(w[i]>=mid));
    }
    ll sum=0;
    for(int i=1;i<=m;i++) {
        sum=(sum+(sum1[r[i]]-sum1[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]));
    }
    return sum;
}
int main() {
    scanf("%d%d%lld",&n,&m,&S);
    for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
    for(int i=1;i<=m;i++) 
        scanf("%d%d",&l[i],&r[i]);
    int L=0,R=1e6;
    while(L<=R) {
        int mid=L+R>>1;
        ll tp=ck(mid);
        if(tp>S) L=mid+1;
        else if(tp==S) {
            printf("%d",0);
            return 0;
        }
        else R=mid-1;
    }
    printf("%d\n",(int)min(abs(ck(R)-S),abs(S-ck(L))));
    return 0;    
}
聪明的质检员

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9770571.html