今天cf太凶残,各种hack狂魔.. 18hack简直sxbk .. 相比之下我的-1hack就是个笑话
A. Devu, the Singer and Churu, the Joker
题意 : 一个人唱歌,一个人讲笑话,唱歌的人每唱一首歌至少要休息10分钟,讲笑话的不用休息,而且每个笑话5分钟。两个人表演的时间最多只能d,给你唱歌的人唱的每首歌的时间长度,问你最多可以将多少个笑话。如果唱歌的人歌都唱不完,那就输出-1
思路 : 反正讲笑话不会影响唱歌的休息...所以就贪心的能唱歌就唱歌就行了
#include<stdio.h>
int main(){
int n , d ;
while( scanf( "%d%d" , &n , &d ) != EOF ) {
int cnt = 0 ;
int time = 0 ;
bool flag = 0 ;
for( int i = 0 ; i < n; i ++ ) {
int a ;scanf( "%d" , &a ) ;
if( time + a <=d ) {
time += a ;
}else{
flag = 1 ;
}
if( time + 10 <= d ) cnt += 2 ;
else if( time + 5 <= d ) cnt += 1 ;
time += 10 ;
}
if( flag == 1 ) {
puts( "-1" ) ;
}else{
if( d >= time ) cnt += ( d - time ) / 5 ;
printf( "%d\n" , cnt ) ;
}
}
return 0 ;
}
B. Devu, the Dumb Guy
题意 : 给你n门课,每门课有ci章,你可以任意安排上课的顺序,上第一门课,每章花x分钟,第二门课每章花x-1分钟 ... 另外每章花费时间最少为1分钟
思路 : 直接做 , 注意别溢出 , 不然会被hack狂魔光顾的
#include <stdio.h>
#include <algorithm>
using namespace std;
__int64 a[100005] , n , x , ans ;
int main(){
while( scanf( "%I64d%I64d" , &n , &x ) != EOF ) {
ans = 0 ;
for( int i = 1 ;i <= n; i ++ ) scanf( "%I64d" , &a[i] ) ;
sort( a + 1 , a + 1 + n ) ;
for( int i = 1 ; i <= n; i ++ ) {
ans += x * a[i] ;
if( x > 1 )
x -- ;
}
printf( "%I64d\n" , ans ) ;
}
return 0 ;
}
C. Devu and Partitioning of the Array
题意 : 给你n个整数 , 你需要分成k份,并且有p份和为偶数 ,可以就输出YES以及任意方案, 不行输出NO
思路 : 首先我们要统计奇数有多少个 , 假设为odd个,如果odd < k - p 那么必然是NO , 因为不可能凑到 k - p 个和为奇数的堆 。 然后剩下的奇数必然要两两配对 , 所以 odd - ( k - p ) 必须是偶数 , 然后最后我们要配出 p 个偶数堆 , 所以 ( odd - ( k - p ) ) / 2 + n - odd 至少要是p个 。这样构造完之后,剩下全部放第一堆就行了。实现的时候要注意细节,最后挂了很多人
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std;
int a[100005] ;
deque<int> Odd , Even ;
vector<int> ans[100005] ;
int main(){
int n , k , p ;
while( scanf( "%d%d%d" , &n , &k , &p ) != EOF ) {
int odd = 0 ;
for( int i = 0 ; i < k ; i ++ ) ans[i].clear() ;
Odd.clear() ; Even.clear() ;
for( int i = 1 ;i <= n ; i ++ ) {
scanf( "%d" , &a[i] ) ;
if( a[i] % 2 == 1 ) {
odd ++ ;
Odd.push_back( a[i] ) ;
}else{
Even.push_back( a[i] ) ;
}
}
int even = n - odd ;
if( odd < k - p ) {
puts( "NO" ) ;
continue ;
}
int t = odd - k + p ;
if( t % 2 == 1 ) {
puts( "NO" ) ;
continue ;
}
if( t / 2 + even < p ) {
puts( "NO" ) ;
continue ;
}
puts( "YES" ) ;
for( int i = 0 ;i < k - p ; i ++ ) {
int tmp = *Odd.begin() ; Odd.pop_front() ;
ans[i].push_back( tmp ) ;
}
int i ;
for( i = k - p ; i < k && Even.size() ; i ++ ) {
int tmp = *Even.begin() ; Even.pop_front() ;
ans[i].push_back( tmp ) ;
}
if( i < k ) {
for( ; i < k ; i ++ ) {
int tmp = *Odd.begin() ; Odd.pop_front() ;
ans[i].push_back( tmp ) ;
tmp = *Odd.begin() ; Odd.pop_front() ;
ans[i].push_back( tmp ) ;
}
int size = Odd.size() ;
for( int i = 0 ; i < size ;i ++ ) {
int tmp = *Odd.begin() ; Odd.pop_front() ;
ans[0].push_back( tmp ) ;
}
}else{
int size = Odd.size() ;
for( int i = 0 ; i < size ;i ++ ) {
int tmp = *Odd.begin() ; Odd.pop_front() ;
ans[0].push_back( tmp ) ;
}
size = Even.size() ;
for( int i = 0 ; i < size ;i ++ ) {
int tmp = *Even.begin() ; Even.pop_front() ;
ans[0].push_back( tmp ) ;
}
}
for( int i = 0 ; i < k ; i ++ ) {
printf( "%d" , ans[i].size() ) ;
for( int j = 0 ; j < ans[i].size() ; j ++ ) {
printf( " %d" , ans[i][j] ) ;
}
puts( "" ) ;
}
}
return 0 ;
}
D. Devu and his Brother
题意 : 给你两个数组,你每次可以是任意一个数组中的一个元素减一或者加一 , 你要让第一个数组的最小值大于等于第二个数组的最大值。
思路 : 其实我们要求的是一个K,使得第一个数组中小于K的都变成K ,第二个数组中大于K的都变成K ,并且加减的和是最小的。我们可以很容易得到一个结论,这个K必然是原本来个数组中的一个数。
证明 : 首先 , 我们很容易就能排序K大于两个数组中所有的数和小于数组中所有数的情况。只需要讨论存在 A < K < B 并且 A ,B 属于两个原来的数组
假如 K 不属于原本的两个任意一个数 , 那么a数组中有ka个数小于K , b数组中kb个数大于K , 那么假设 Ka = Kb , 那么K取A和B的值是不会变的。那么如果Ka 大于 Kb , 那么选择A会较优 , 反之选择B会较优。
所有最优的K一定是原来数组中数字。
那么直接枚举两个数组中的数字即可 , 计算的话通过预处理之后,每个K只要O(1)就能求出,所以总的只要O(n)
这题还可以三分之类,写的时候没想那么多
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
__int64 a[100005] , b[100005] ;
__int64 suma[100005] , sumb[100005] ;
__int64 ans ;
int main(){
int n , m ;
while( scanf( "%d%d" , &n , &m ) != EOF ) {
ans = 0x3f3f3f3f3f3f3f ;
for( int i = 1 ; i <= n ; i ++ )
scanf( "%I64d" , &a[i] ) ;
for( int i = 1; i <= m; i ++ )
scanf( "%I64d" , &b[i] ) ;
sort( a + 1 , a + 1 + n ) ;
sort( b + 1 , b + 1 + m ) ;
for( int i = 1 ;i <= n; i ++ ) {
suma[i] = suma[i-1] + a[i] ;
}
for( int i = m ; i >= 1 ; i -- ) {
sumb[i] = sumb[i+1] + b[i] ;
}
int ii = 1 , jj = 1 ;
for( ii = 1 ; ii <= n ; ii ++ ) {
for( ; jj <= m ; jj ++ ) {
if( b[jj] >= a[ii] ) break;
}
__int64 cost = 0 ;
cost = ( ii - 1 ) * a[ii] - suma[ii-1] + ( sumb[jj] - ( m - jj + 1 ) * a[ii] ) ;
ans = min( ans , cost ) ;
}
ii = n , jj = m ;
for( jj = m ; jj >= 1 ; jj -- ) {
for( ; ii >= 1 ; ii -- ) {
if( a[ii] <= b[jj] ) break;
}
__int64 cost = 0 ;
cost = ii * b[jj] - suma[ii] + ( sumb[jj] - ( m - jj + 1 ) * b[jj] ) ;
ans = min( ans , cost ) ;
}
printf( "%I64d\n" , ans ) ;
}
return 0 ;
}