hdu 5101 单调+二分查找
2015-02-06 11:49
211 查看
因为每次要找其他班和自己相加之和大于固定值的人数的个数,所以先排序,利用二分查找找到满足条件的最小值,然后后面的均符合条件,利用容斥定理中的补集关系,让总的排列中满足条件的个数-自己班中满足条件的个数=其他班满足条件的个数,二分查找自己写的,不熟悉的可以用stl里的upper_bound函数
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #define MAX 1007 #define N 107 using namespace std; int a[MAX] ; int b[MAX*N]; int sum[MAX]; bool cmp ( int a , int b ) { return a > b; } int get ( int v , int a[] , int len ) { int left = 1 , right = len , mid; while ( left < right ) { mid = (left + right+1) >> 1; if ( a[mid] > v ) left = mid; else right = mid -1; } if ( a[left] > v ) return left; else return 0; } int main ( ) { int t,n,k,iq; scanf ( "%d" , &t ); while ( t-- ) { scanf ( "%d%d" , &n , &k ); long long ans = 0; int cnt = 1; for ( int i = 1 ; i <= n ; i++ ) { scanf ( "%d" , &sum[i] ); for ( int j = 1 ; j <= sum[i] ; j++ ) { scanf ( "%d" , &a[i][j] ); b[cnt++] = a[i][j]; } sort ( a[i]+1 , a[i]+sum[i]+1 , cmp ); } sort ( b+1 , b+cnt , cmp ); for ( int i = 1 ; i <= n ; i++ ) for ( int j = 1 ; j <= sum[i] ; j++ ) { long long temp = get ( k-a[i][j] , b , cnt-1 ); temp -= get ( k-a[i][j] , a[i] , sum[i] ); ans += temp; } printf ( "%I64d\n" , ans/2 ); } }
相关文章推荐
- hdu 5101 Select (二分+单调)
- hdu 5101 Select【二分查找】
- 最长单调递增子序列(二分查找优化)
- hdu 2141 二分查找
- HDU 2199 || HDU 2899 (二分查找+数学问题)
- HDU 4430 Yukari's Birthday二分查找
- hdu 4004(The Frog's Games) 二分查找
- hdu 2136 Largest prime factor【数论、动态规划、二分查找】
- 二分查找单调队列
- HDU 4282 A very hard mathematic problem(二分查找)
- HDU 2141 二分查找,实现上简单,思想很重要
- hdu 1969 二分查找
- hdu 4004 二分查找
- HDU 2446 Shell Pyramid 二分查找
- HDU 2871 Memory Control 线段树(区间合并)+二分查找+vector的常用方法
- HDU 2199 || HDU 2899 (二分查找+数学问题)
- hdu 2446 二分查找
- hdu 2141 Can you find it? 二分查找
- 二分查找求函数的区间最小值&&http://acm.hdu.edu.cn/showproblem.php?pid=2899
- HDU 3622 Bomb Game( 二分查找+2-SAT )