Codeforces Round #523 (Div. 2) A模拟 B 贪心 排序 C dp D贪心排序

A

Code:

#include <bits/stdc++.h>
using namespace std ; 
int main(){
	int n , S ; 
	cin >> n >> S ;
	int res = S / n ; 
	S -= res * n ; 
	if( S ) res ++ ; 
	cout << res << endl  ;
	return 0 ; 
}

B

Code:
思路不清晰写出来像一坨shi

#include <bits/stdc++.h>
#define LL long long 
using namespace std ;
const int AX = 1e5 + 666 ;
LL a[AX] ; 
int main(){
	int n , m ; 
	cin >> n >> m ; 
	for( int i = 0 ; i < n ; i++ ){
		cin >> a[i] ; 
	}
	if( n == 1 ){
		cout << 0 << endl;
		return 0 ; 
	}
	sort( a , a + n );
	LL res = 0LL ; 
	int cur = a[n-1] + 1 ; 
	for( int i = n - 1 ; i > 0 ; i-- ){
		if( a[i] == a[i-1] ){
			res += a[i] - 1 ; 
			cur -- ; 
		}else{
			if( cur - 1 <= a[i-1] ){
				res += a[i] - 1 ; 
				cur -- ; 
			}else{
				res += a[i-1] ; 
				res += a[i] - cur + 1 ;
				cur = a[i-1] + 1 ; 
			}
		}
		if( cur <= 2 ){
			for( int j = i - 1 ; j >= 0 ; j-- ){
				res += a[j] - 1 ;
			}
			break ; 
		} 
	}
	if( cur > 2 ){
		res += a[0] - cur + 1 ; 
	}
	cout << res << endl;
	return 0 ; 	
}

思路清晰版本:

#include <bits/stdc++.h>
#define LL long long 
using namespace std ;
const int AX = 1e5 + 666 ;
LL a[AX] ; 
int main(){
	int n , m ; 
	cin >> n >> m ; 
	LL sum = 0LL ;
	for( int i = 1 ; i <= n ; i++ ){
		cin >> a[i] ; 
		sum += a[i] ; 
	}
	sort( a + 1 , a + n + 1 ) ;
	LL cur = a[n] ; 
	LL res = 0LL ; 
	for( int i = n ; i >= 1 ; i-- ){
		res += max( 1LL , cur - a[i-1] ) ; 
		cur = min( cur - 1 , a[i-1] ) ; 
	}
	cout << sum - res << endl ; 
	return 0 ; 	
}

C
题意:找出有多少个a数组的子序列b , 使得b1,b2,b3…bk, 对于每个bi , i 整除 bi
思路:dp[i][j] 表示到第 i 个数 子串b 长度 j 且满足条件的数量。
dp[i][j] = dp[i-1][j-1] + dp[i][j] .
但是…开不了这么大的,那么就要省掉一维。
先预处理出1e6的因子,从大到小存,这是为了后面正序遍历(也可以倒序因子正序,只要保证先访问大因子就行)的时候 前面小的因子 不会影响 i 的结果,而i的结果是由i-1得到的。
Code:

#include <bits/stdc++.h>
#define LL long long 
using namespace std ;
const int AX = 1e6 + 666 ;
const int MOD = 1e9 + 7 ;
int dp[AX] = { 1 } ;  
int n ;
std::vector<int> v[AX];
void getFac(){
	for( int i = 1000000 ; i >= 1 ; i-- ){
		for( int j = i ; j <= 1000000 ; j += i ){
			v[j].push_back(i) ; 
		}
	}
} 

int main(){
	getFac() ; 
	scanf("%d",&n) ; 
	int x ; 
	for( int i = 1 ; i <= n ; i++ ){
		scanf("%d",&x) ; 
		for( int j = 0 ; j < v[x].size() ; j++ ){
			int id = v[x][j] ; 
			dp[id] += dp[id-1] ; 
			dp[id] %= MOD ; 
		}
	}
	LL res = 0LL ; 
	for( int i = 1 ; i <= n ; i++ ){
		res += dp[i] ; 
		res %= MOD ; 
	}
	cout << res << endl;
	return 0 ; 	
}

D

思路:
让 r 从大到小遍历 , 按照 l 从小到大排序,每次二分查找比当前 r 大的数,如果这个数所在的集合左端点<= r ,那么就往后继续找满足的解,直到到头了或者x < y * ( r - l ) ,也就是开一个新的TV集合会更省钱。
最后记得加上没人组合的,独自一个集合。
Code:

#include <bits/stdc++.h>
#define LL long long 
#define INF 1000000007
using namespace std ; 
const int MOD = 1e9 + 7 ; 
const int AX = 1e5 + 666 ; 
int mark[AX] ;
struct Node{
	LL l , r ;
	int id ; 
	bool friend operator < ( const Node &a , const Node &b ){
		return ( ( a.l == b.l && a.r < b.r ) || a.l < b.l ) ; 
	}
}a[AX];
struct NO{
	LL l , r ;
	int id ; 
}c[AX];
Node b[AX] ; 
int n ;
LL x , y ; 
bool cmp( NO a , NO b ){
	return a.r > b.r ; 
}
int binary_search( LL x ){
	int l = 0 , r = n - 1 ;  
	while( l <= r ){
		int mid = ( l + r ) >> 1 ;
		if( a[mid].l > x ){
			r = mid - 1 ; 
		}else{
			l = mid + 1 ; 
		}
	}
	return l ; 
}
int main(){
	scanf("%d%I64d%I64d",&n,&x,&y) ;
	for( int i = 0 ; i < n ; i ++ ){
		scanf("%I64d%I64d",&a[i].l,&a[i].r) ; 
		a[i].id = i ;
		c[i].id = i ; 
		c[i].l = a[i].l ;
		c[i].r = a[i].r ; 
	}
	memset( mark , 0 , sizeof(mark) ) ; 
	sort( a , a + n ) ; 
	sort( c , c + n , cmp ) ; 
	LL res = 0LL ;
	int tot = 1 ; 
	for( int i = 0 ; i <= n ; i++ ){
		b[i].l = INF ; 
		b[i].r = 0 ; 
	}
	for( int i = 0 ; i < n ; i++ ){
		int pos = binary_search( c[i].r ) ; 
		if( pos < 0 || pos >= n || ( 1LL * y * ( a[pos].l - c[i].r ) > x ) ){
			continue;
		}
		int id ; 
		if( !mark[a[pos].id] ){
			mark[c[i].id] = tot ;
			mark[a[pos].id] = tot ;
			id = tot ++ ; 
		}else{
			id = mark[a[pos].id] ;  
			if( b[id].l <= c[i].r ){
				while( pos < n && ( 1LL * y * ( a[pos].l - c[i].r ) < x ) && b[mark[a[pos].id]].l <= c[i].r ) pos ++ ; 
				if( pos < n && ( 1LL * y * ( a[pos].l - c[i].r ) < x ) && b[mark[a[pos].id]].l > c[i].r ){
					if( !mark[a[pos].id] ){
						mark[c[i].id] = tot ;
						mark[a[pos].id] = tot ;
						id = tot ++ ;
					}else{
						id = mark[a[pos].id] ; 
					}
				}else continue ; 
			}
			mark[c[i].id] = id ; 
		}
		b[id].l = min( b[id].l , c[i].l ) ; 
		b[id].r = max( b[id].r , a[pos].r ) ;
	}
	for( int i = 1 ; i < tot ; i++ ){
		res = ( res + x % MOD + 1LL * y * ( b[i].r - b[i].l ) % MOD ) % MOD ; 
	}
	for( int i = 0 ; i < n ; i++ ){
		if( !mark[a[i].id] ){
			res = ( res + x % MOD + 1LL * y * ( a[i].r - a[i].l ) % MOD ) % MOD ; 
		} 
	}
	printf("%I64d\n",res);
	return 0 ; 
}

简洁Code:

#include <bits/stdc++.h>
#define LL long long 
#define INF 1000000007
using namespace std ; 
const int MOD = 1e9 + 7 ; 
const int AX = 1e5 + 666 ; 
int n ;
LL a[AX];
LL b[AX];
int mark[AX] ; 
LL x , y ; 
int main(){
	scanf("%d%I64d%I64d",&n,&x,&y) ;
	LL res = 0LL ;
	for( int i = 0 ; i < n ; i ++ ){
		scanf("%I64d%I64d",&a[i],&b[i]) ;  
		res = ( res + x % MOD + 1LL * y * ( b[i] - a[i] ) ) % MOD ; 
	}
	memset( mark , 0 , sizeof(mark) ) ; 
	sort( a , a + n ) ; 
	sort( b , b + n ) ; 
	for( int i = n - 1 ; i >= 0 ; i-- ){
		int pos = upper_bound( a , a + n , b[i] ) - a ; 
		if( pos < 0 || pos >= n || ( 1LL * y * ( a[pos] - b[i] ) > x ) ){
			continue;
		}
		while( pos <= n && mark[pos] && ( 1LL * y * ( a[pos] - b[i] ) < x ) ) pos ++ ;
		if( pos >= n ) continue ; 
		if( 1LL * y * ( a[pos] - b[i] ) < x ){
			mark[pos] = 1 ; 
			res = ( res + MOD - x + 1LL * y * ( a[pos] - b[i] ) ) % MOD ; 
		} 
	}
	printf("%I64d\n",res);
	return 0 ; 
}

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/84571264