• 二分的两种板子


    P1314 聪明的质监员为例
    第一种写法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int N=200000+10;
    int v[N],w[N],n,m;
    int l[N],r[N];
    int sum[N],cnt[N];
    LL f(int W)
    {
        memset(sum,0,sizeof(sum));
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)
        {
            if(w[i]>=W)
            {
                cnt[i]=cnt[i-1]+1;
                sum[i]=sum[i-1]+v[i];
            }
            else
            {
                cnt[i]=cnt[i-1];
                sum[i]=sum[i-1];
            }
        }
        LL res=0;
        for(int i=1;i<=m;i++)
        {
            res=res+(sum[r[i]]-sum[l[i]-1])*(cnt[r[i]]-cnt[l[i]-1]);
        }
        return res;
    }
    int main()
    {
        LL S;
        cin>>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=1000000+1,mid;
        while(L<R)                   //这里求的是 递减函数的 函数值严格小于S的  点的横坐标 的最小值 
        {
            mid=(L+R)/2;      //下取整的板子 
            if(f(mid)<S)
                R=mid;      //mid处函数值小于S,不能保证mid-1处函数值小于S,只能将R缩小至mid 
            else
                L=mid+1;      //mid处函数值大于等于S,可直接令L缩至mid+1         最终L和R必相等,不会死循环
        }                         
        cout<<min(S-f(L),f(L-1)-S)<<endl;
        return 0;
    }

    第二种写法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int N=200000+10;
    int v[N],w[N],n,m;
    int l[N],r[N];
    int sum[N],cnt[N];
    LL f(int W)
    {
        memset(sum,0,sizeof(sum));
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)
        {
            if(w[i]>=W)
            {
                cnt[i]=cnt[i-1]+1;
                sum[i]=sum[i-1]+v[i];
            }
            else
            {
                cnt[i]=cnt[i-1];
                sum[i]=sum[i-1];
            }
        }
        LL res=0;
        for(int i=1;i<=m;i++)
        {
            res=res+(sum[r[i]]-sum[l[i]-1])*(cnt[r[i]]-cnt[l[i]-1]);
        }
        return res;
    }
    int main()
    {
        LL S;
        cin>>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=1000000+1,mid;
        while(L<R)                   //这里求的是 递减函数的 函数值大于等于S的  点的横坐标 的最大值 
        {
            mid=(L+R+1)/2;      //上取整的板子 
            if(f(mid)>=S)
                L=mid;      //mid处函数值大于等于S,不能保证mid+1处函数值大于等于S,只能将L缩小至mid 
            else
                R=mid-1;      //mid处函数值小于S,可直接令R缩至mid-1         最终L和R必相等,不会死循环
        }                         
        cout<<min(f(L)-S,S-f(L+1))<<endl;
        return 0;
    }
  • 相关阅读:
    本地项目上传到github
    linux 常用命令
    mysql 查询日志基本操作
    js 短信60秒倒计时
    windows下 mysql 移库
    INSERT INTO table(xxx) VALUES (xxx)
    springboot 项目接口调用失败
    P1093 奖学金
    P1403约数研究
    P1147连续自然数和
  • 原文地址:https://www.cnblogs.com/spzeno/p/11242542.html
Copyright © 2020-2023  润新知