NOIP2011提高组 聪明的质检员

来源:互联网 发布:mac电脑截图 编辑:程序博客网 时间:2024/04/28 06:58

这里写图片描述

这道题很明显要用二分猜答案,猜w的值,再来check。这里我用的前缀和的方法来check,求出前i个大于w 的个数和价值和,然后枚举每一个区间,算就好了。
注:要注意用longlong(考试的时候我就是这个错了)。
具体程序如下:

#include<cstdio>#include<cstdlib>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn=200005;struct shu{    int w,v;}a[maxn];struct data{    int x,y,id;}b[maxn];long long n,m,s,g[maxn][3];long long read(){    long long x=0,ok=0;    char ch;    ch=getchar();    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();    while((ch>='0'&&ch<='9')||ch=='-')    {        if(ch=='-') ok=1;        else x=x*10+ch-'0';        ch=getchar();    }    return ok==1?-x:x;}void init(){    n=read();    m=read();    s=read();    for(int i=1;i<=n;i++)    {        a[i].w=read();        a[i].v=read();    }    for(int j=1;j<=m;j++)    {        b[j].x=read();        b[j].y=read();    }}long long check(long long x){    long long ans=0;    for(int i=1;i<=n;i++)    {        if(a[i].w>=x)        {            g[i][1]=g[i-1][1]+1;            g[i][0]=g[i-1][0]+a[i].v;        }        else        {            g[i][1]=g[i-1][1];            g[i][0]=g[i-1][0];        }    }    for(int i=1;i<=m;i++)    {        long long x1=g[b[i].y][1]-g[b[i].x-1][1];        long long x2=g[b[i].y][0]-g[b[i].x-1][0];        ans+=x1*x2;    }    return ans;}int main(){    //freopen("qc.in","r",stdin);    //freopen("qc.out","w",stdout);    init();    int x=0,y=1000000;    long long ans=10000000000000000ll;    while(x<=y)    {        int z=(x+y)/2;        long long p=check(z);        if(p>s) x=z+1;        if(p<s) y=z-1;        if(p==s)        {            printf("0");            return 0;        }        ans=min(ans,abs(p-s));    }    cout<<ans;    return 0;}
1 0
原创粉丝点击