洛谷 1314 聪明的质监员——二分答案

题目:https://www.luogu.org/problemnew/show/P1314

二分答案。把询问挂在右边界上,就能用前缀查询了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=2e5+5;
int n,m,w[N],v[N],hd[N],xnt,to[N],nxt[N],l,r,mid,ct[N];
ll S,ans=1e13,sm[N],sum;
int rdn()
{
    int ret=0;bool fx=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return fx?ret:-ret;
}
void add(int x,int y)
{
    to[++xnt]=y; nxt[xnt]=hd[x]; hd[x]=xnt;
}
int main()
{
    n=rdn(); m=rdn(); scanf("%lld",&S);
    for(int i=1;i<=n;i++)
    {
        w[i]=rdn();v[i]=rdn();
        r=max(r,w[i]);
    }
    r++;
    for(int i=1,x,y;i<=m;i++)
    {
        x=rdn(); y=rdn(); add(y,x-1);
    }
    while(l<=r)
    {
        mid=l+r>>1; sum=0;
        for(int i=1;i<=n;i++)
        {
            sm[i]=sm[i-1]+(w[i]>=mid?v[i]:0);
            ct[i]=ct[i-1]+(w[i]>=mid?1:0);
            for(int j=hd[i];j;j=nxt[j])
                sum+=(sm[i]-sm[to[j]])*(ct[i]-ct[to[j]]);
        }
        if(sum>=S) ans=min(ans,sum-S),l=mid+1;
        else ans=min(ans,S-sum),r=mid-1;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/9686391.html