欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【NOIP 2011 提高组 Day2】聪明的质监员

程序员文章站 2022-04-02 18:49:50
...

题目

【NOIP 2011 提高组 Day2】聪明的质监员


题解

–这道题吧,就是题目中求Yi的公式很恶心罢了
宝宝来翻译一下,就是在 [Li,Ri] 的区间中,所有满足 wj>W 的矿石的数量 * 他们的价值之和
–这样就简单了,只需要二分查找一下就好(加上前缀和优化)
对于一个mid,发现:
1. 如果Y>S,说明入选的矿石多了,应把mid调大,即L=mid+1
2. 如果Y

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=200005;

int n,m;
long long s;
int w[MAXN],v[MAXN];
int l[MAXN],r[MAXN];
int L=0x3f3f3f3f,R;
long long vs[MAXN],ss[MAXN];
long long ans=0x7f7f7f7f7f;


int main(){
//  freopen("qc.in","r",stdin);
//  freopen("qc.out","w",stdout);
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&w[i],&v[i]);
        L=min(L,w[i]);
        R=max(R,w[i]);
    }
    for(int i=1;i<=m;i++)
        scanf("%d%d",&l[i],&r[i]);
    L=L-1;
    R=R+2;
    while(L<=R){
        long long W=(L+R)/2;
        memset(vs,0,sizeof(vs));
        memset(ss,0,sizeof(ss));
        for(int i=1;i<=n;i++){
            vs[i]=vs[i-1];
            ss[i]=ss[i-1];
            if(w[i]>=W){
                vs[i]+=v[i];
                ss[i]+=1;
            }
        }
        long long Y=0;
        for(int i=1;i<=m;i++)
            Y+=(ss[r[i]]-ss[l[i]-1])*(vs[r[i]]-vs[l[i]-1]);
        if(Y>s)
            L=W+1;
        else
            R=W-1;
        if(abs(Y-s)<ans)
            ans=abs(Y-s);
    }
    cout<<ans;
    return 0;
}
相关标签: 刷题之路