题目链接

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 ;
}