洛谷 P1314 聪明的质监员

传送门:洛谷 P1314 聪明的质监员
算法分析:

调整参数\(W\)的值,让检验结果尽可能的靠近标准值\(S\),即使得\(|S-Y|\)最小。请你帮忙求出这个最小值。
其中 \(Y_i=\sum_j1\times\sum_jv_j, j\in[L_i,R_i] \ \cap \ w_j\geq W\)
不难发现,当\(W\)增大时,\(Y\)一定随之增大,这题可用二分的思想:即二分\(W\),计算出\(Y\)值(前缀和优化)


绝对值的处理:

如图所示的是 \(y=|x-3|\) 的函数图像
不难发现,图像以 \((3,0)\) 为界,左侧单调减,右侧单调增,两侧单调性不同
故若要求 \(|S-Y|\) 的最小值,要从两旁逼近:
1、\(S<Y\)\(S\) 应增大
2、\(S>Y\), \(S\) 应减小


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=200000;
const long long inf=0x7ffffffffffffff;
struct Node
{
    int v,w;
}a[maxN+1];
inline int read();
int n,m,box[maxN+1][2],L=999999999,R=0;;
long long S,ans=inf,b[maxN+1],c[maxN+1],sum;
bool calc(int);
int main()
{
    n=read(); m=read(); scanf("%lld",&S);
    for(int i=1;i<=n;i++)
    {
        a[i].w=read();
        a[i].v=read();
        L=min(L,a[i].w); R=max(R,a[i].w);
    }
    for(int i=1;i<=m;i++)
    {
        int x=read();
        int y=read();
        box[i][0]=x; box[i][1]=y;
    }
    int l=L-1,r=R+1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(calc(mid)) l=mid+1;
        else r=mid-1;
        ans=min(ans,abs(S-sum));
    }
    printf("%lld",ans);
    return 0;
}
bool calc(int W)
{
    sum=0;
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    for(int i=1;i<=n;i++)
        if(a[i].w<W) {b[i]=b[i-1]; c[i]=c[i-1];}
        else {b[i]=b[i-1]+a[i].v; c[i]=c[i-1]+1;}
    for(int i=1;i<=m;i++)
        sum+=(b[box[i][1]]-b[box[i][0]-1])*(c[box[i][1]]-c[box[i][0]-1]);
    if(sum>S) return true;
    else return false;
}
inline int read()
{
    int num=0,f=1;
    char ch=getchar();
    while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if(ch=='-') {f=-1; ch=getchar();}
    while(ch>='0' && ch<='9')
    {
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

猜你喜欢

转载自www.cnblogs.com/ezsyshx/p/10359331.html