Codeforces 589G Hiring(BIT + 二分)
2015-10-19 18:04
573 查看
2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest G.Hiring
每一个应聘者都有对应的工作要求,第 i 个应聘者每天要花 di 小时用于工作前准备,总工作量为 ri 小时(不包括准备时间)。
准备工作与完成工作都需要在办公室内进行,如果当天办公室可使用时间小于准备时间,将无法开始工作。
求每一个应聘者最早能在第几天完成工作。
用两个树状数组维护对于每一个应聘者的办公室第i天之前(包括第i天)的可工作天数,与办公室可工作时间,可工作的定义为可使用时间不小于准备时间。
若第i天之前的可工作天数*准备时间(di) + 总工作量(ri) <= 第i天之前的可工作时间,那么第i天即可完成所有工作。
然后二分答案,求出最小i即可。
另外分块算法也可以水过。
题意:
一家公司对 n 个应聘者做能力评估,要求他们在最多 m 天内完成指定工作,第 j 天可以使用办公室的时间为 tj 小时。每一个应聘者都有对应的工作要求,第 i 个应聘者每天要花 di 小时用于工作前准备,总工作量为 ri 小时(不包括准备时间)。
准备工作与完成工作都需要在办公室内进行,如果当天办公室可使用时间小于准备时间,将无法开始工作。
求每一个应聘者最早能在第几天完成工作。
思路:
先对办公室可使用时间进行升序排序,再依据准备时间对每一个应聘者进行升序排序。用两个树状数组维护对于每一个应聘者的办公室第i天之前(包括第i天)的可工作天数,与办公室可工作时间,可工作的定义为可使用时间不小于准备时间。
若第i天之前的可工作天数*准备时间(di) + 总工作量(ri) <= 第i天之前的可工作时间,那么第i天即可完成所有工作。
然后二分答案,求出最小i即可。
代码:
BIT可做题一般线段树也可做,但这题BIT相对好写一些。另外分块算法也可以水过。
//2015/10/18 23:03:07 //#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<functional> #include<string> #include<map> #include<set> #include<vector> #include<queue> #include<stack> #include<bitset> #include<ctime> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define pr( x ) cout << #x << " = " << x << endl #define pri( x ) cout << #x << " = " << x << " " #define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- ) #define out( kase ) printf( "Case %d: " , kase++ ) #define sqr( x ) ( x * x ) #define lowbit( x ) ( x & -x ) #define mp make_pair #define pii pair<int,int> #define fi first #define se second #define pb push_back typedef long long lint; typedef unsigned long long ULL; const double eps = 1e-8 ; const int inf = 0x3f3f3f3f ; const long long INF = 0x3f3f3f3f3f3f3f3fLL ; const int maxn = 2 * 1e5 + 5 ; struct C{ int d , r , id ; bool operator < ( const C &a )const { return d < a.d ; } }c[maxn] ; struct Day{ int t , id ; bool operator < ( const Day &a ) const { return t < a.t ; } }day[maxn] ; int n , m , ans[maxn] ; lint sum[maxn<<2] , cnt[maxn<<2] ; lint query( lint C[] , int x ) { lint res = 0 ; while ( x ) { res += C[x] ; x -= lowbit( x ) ; } return res ; } void add( lint C[] , int x , int d ) { while ( x <= m ) { C[x] += d ; x += lowbit( x ) ; } } bool check( int x , int i ) { lint tmp1 = query( sum , x ) ; lint tmp2 = query( cnt , x ) ; if ( tmp2 * c[i].d + c[i].r <= tmp1 ) return true ; return false ; } int main() { while ( cin >> n >> m ) { cls( cnt ) ; cls( sum ) ; for ( int i = 1 ; i <= m ; i++ ) scanf( "%d" , &day[i].t ) , day[i].id = i ; for ( int i = 1 ; i <= n ; i++ ) scanf( "%d%d" , &c[i].d , &c[i].r ) , c[i].id = i ; sort( day + 1 , day + m + 1 ) ; sort( c + 1 , c + n + 1 ) ; int j = m ; for ( int i = n ; i >= 1 ; i-- ) { while ( j && day[j].t >= c[i].d ) { add( sum , day[j].id , day[j].t ) ; add( cnt , day[j].id , 1 ) ; j-- ; } int L = 1 , R = m + 1 ; while ( L < R ) { int mid = ( L + R ) >> 1 ; if ( check( mid , i ) ) R = mid ; else L = mid + 1 ; } if ( L == m + 1 ) ans[c[i].id] = 0 ; else ans[c[i].id] = L ; } for ( int i = 1 ; i <= n ; i++ ) { if ( i > 1 ) printf( " " ) ; printf( "%d" , ans[i] ) ; } puts( "" ) ; } return 0; }
相关文章推荐
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构揭秘一
- 数据结构之Treap详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)
- java数据结构和算法学习之汉诺塔示例
- Java数据结构及算法实例:三角数字
- Java数据结构之简单链表的定义与实现方法示例
- 数据结构之AVL树详解
- qqwry.dat的数据结构图文解释第1/2页
- JavaScript中数据结构与算法(五):经典KMP算法