首页 > 其他 > 详细

【NOIP2011提高组】聪明的质监员(二分查找+前缀和优化)

时间:2020-03-04 12:33:03      阅读:61      评论:0      收藏:0      [点我收藏+]

题目地址:https://www.luogu.com.cn/problem/P1314

这题如此得水我为何要写博客,走人了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define Re register
#define LL long long

using namespace std;
inline LL read() {
    LL x = 0;
    char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    return x;
}
const int maxN = 200005;
LL N, M, S, w[maxN], v[maxN], sumt[maxN], sumv[maxN], MAX, l[maxN], r[maxN];
LL check(LL W) {
    LL res = 0;
    memset(sumt, 0, sizeof(sumt));
    memset(sumv, 0, sizeof(sumv));
    for (int i = 1; i <= N; ++i) {
        sumt[i] += sumt[i - 1], sumv[i] += sumv[i - 1];
        if (w[i] >= W) sumv[i] += v[i], ++sumt[i];
    }
    for (int i = 1; i <= M; ++i) {
        res += (sumt[r[i]] - sumt[l[i] - 1]) * (sumv[r[i]] - sumv[l[i] - 1]);
    }
    return res;
}
LL Ans;
int main() {    
    N = read(), M = read(), S = read();
    for (int i = 1; i <= N; ++i) {
        w[i] = read(), v[i] = read();    
        MAX = max(MAX, w[i]);    
    }
    for (int i = 1; i <= M; ++i) 
        l[i] = read(), r[i] = read();
    int L = 0, R = MAX, ans = 0, mid;
    while (L <= R) {
        mid = (L + R) / 2;
        if (check(mid) <= S) ans = mid, R = mid - 1;
        else L = mid + 1;
    }
    LL tmp = check(ans);
    Ans = (tmp - S) < 0 ? (S - tmp) : (tmp - S);
    L = 0, R = MAX, mid, ans = MAX;
    while (L <= R) {
         mid = (L + R) / 2;
         if (check(mid) >= S) ans = mid, L = mid + 1;
         else R = mid - 1;
    }
    tmp = check(ans);
    LL now = (tmp - S) < 0 ? (S - tmp) : (tmp - S);
    Ans = min(Ans, now);
    printf("%lld\n", Ans);
    return 0;
} 

 

【NOIP2011提高组】聪明的质监员(二分查找+前缀和优化)

原文:https://www.cnblogs.com/blog-fgy/p/12408438.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!