浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

Luogu P1314 聪明的质监员 二分答案

题目链接

Solution

这个范围不是二分就是结论题就是数学题...

然后再看一会差不多就可以看出来有单调性所以就可以确定二分的解法了

二分那个$W$,用前缀和$O(n+m)$的时间来求出对答案的贡献

另外求答案的那个式子我一开始看错了...然后忘记乘符合条件的个数了...

还有答案的上界要取$10^{12}$,$10^{12}$是大于$0x7ffffff$的...然后我就挂了半个小时...

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <set>

using namespace std ;

#define N 200010
#define int long long

int n , m , S ;
int c[ N ] , w[ N ] , v[ N ] , s[ N ] ;

struct node {
    int l , r ;
} a[ N ] ;

int check( int x ) {
    int sum = 0 ;
    c[ 0 ] = 0 ; s[ 0 ] = 0 ;
    for( int i = 1 ; i <= n ; i ++ ) {
        c[ i ] = c[ i - 1 ] ;
        s[ i ] = s[ i - 1 ] ;
        if( w[ i ] >= x ) s[ i ] ++ , c[ i ] += v[ i ] ;
    }
    for( int i = 1 ; i <= m ; i ++ ) {
        sum += ( c[ a[ i ].r ] - c[ a[ i ].l - 1 ] ) * ( s[ a[ i ].r ] - s[ a[ i ].l - 1 ] ) ;
    }
    return sum ;
}

signed main() {
    int l = 01 , r = 0 ;
    scanf( "%lld%lld%lld" , &n , &m , &S ) ;
    for( int i = 1 ; i <= n ; i ++ ) {
        scanf( "%lld%lld" , &w[ i ] , &v[ i ] ) ;
        r = max( r , w[ i ] ) ;
    }
    for( int i = 1 ; i <= m ; i ++ ) {
        scanf( "%lld%lld" , &a[ i ].l , &a[ i ].r ) ;
    }
    int ans = 1e12 ;
    while( l <= r ) {
        int mid = ( l + r ) >> 1 ;
        int x = check( mid ) ;
        if( x >= S ) l = mid + 1 ;
        else r = mid - 1 ;
        ans = min( ans , abs(x-S) ) ;
    }
    printf( "%lld\n" , ans ) ;
    return 0 ;
}

 

posted @ 2018-11-01 17:53  henry_y  阅读(136)  评论(0编辑  收藏  举报