比赛链接
I Interesting Computer Game 并查集维护每个点是否在环内。 题意: 每次给你n个pair,每个pair有两个数a,b,现在要求每次在a,b中选一个,并且选的那个不能是之前选过的数。 解法: 每次输入a,b就在数a,b之间连一条双向边,然后设答案为所有的点都能取到,最后遍历每个团,如果一个团里不含有环,就是n个点(n-1)条边的情况,那必然答案有个点取不到,而有环的团一定有大于等于点数的边数,不用减。 要注意处理读入时赋予顶点编号的先后关系,如某个pair是3 3。 还是数组要开2倍,因为每个pair会有两个不同的数。 初始化时候要注意范围。
* * #include < bits/ stdc++ . h>
using namespace std;
const int maxn= 2 * ( int ) 1e5 + 100 ;
int tc, n, fa[ maxn] , circle[ maxn] ;
int findRoot ( int x) {
if ( x== fa[ x] ) return x;
else {
return fa[ x] = findRoot ( fa[ x] ) ;
}
}
void uniRoot ( int a, int b) {
int aa= findRoot ( a) ;
int bb= findRoot ( b) ;
if ( aa!= bb) {
fa[ bb] = aa;
circle[ aa] | = circle[ bb] ;
} else circle[ aa] = 1 ;
}
int main ( ) {
ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. precision ( 10 ) ; cout << fixed;
#ifdef LOCAL_DEFINE
freopen ( "input.txt" , "r" , stdin ) ;
#endif
int kase= 1 ;
cin>> tc;
while ( tc-- ) {
cin>> n;
for ( int i= 0 ; i<= 200010 ; ++ i) {
fa[ i] = i;
circle[ i] = 0 ;
}
map< int , int > cnt;
int tot= 0 ;
for ( int i= 0 ; i< n; ++ i) {
int a, b;
cin>> a>> b;
int na= cnt[ a] ;
if ( ! na) {
cnt[ a] = ++ tot;
na= tot;
}
int nb= cnt[ b] ;
if ( ! nb) {
cnt[ b] = ++ tot;
nb= tot;
}
uniRoot ( na, nb) ;
}
int ans= tot;
for ( int i= 1 ; i<= tot; ++ i) {
if ( findRoot ( i) == i) {
if ( circle[ i] == 0 ) -- ans;
}
}
cout<< "Case #" << kase++ << ": " << ans<< '\n' ;
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock ( ) / CLOCKS_PER_SEC << " s.\n" ;
#endif
return 0 ;
}
* *
K Kabaleo Lite 题意: 有n个物品,每个物品都有数量和利润,每个客人来一定要拿走1~n连续个数的物品,现在问你最多能来多少客人,利润是多少。 解法: 读题后要明确题目第一优先级是来最多数目的客人,然后才是最大化利润。 首先最多能来的客人就是第一个利润前缀和为正的那个位置物品的个数。 然后每次前缀和达到新高值就放在某个vector里,然后从后往前遍历,更新答案就行辣。 极限情况是1e5*1e5*1e9=1e19超long long,这时候就要用牛客特色的__int128,或者用两个longlong存。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn= ( ll) 1e5 + 100 ;
ll tc, n, a[ maxn] , b[ maxn] , pre[ maxn] ;
__int128 read ( ) {
__int128 x= 0 , f= 1 ;
char ch= getchar ( ) ;
while ( ch< '0' || ch> '9' ) {
if ( ch== '-' )
f= - 1 ;
ch= getchar ( ) ;
}
while ( ch>= '0' && ch<= '9' ) {
x= x* 10 + ch- '0' ;
ch= getchar ( ) ;
}
return x* f;
}
void print ( __int128 x) {
if ( x< 0 ) {
putchar ( '-' ) ;
x= - x;
}
if ( x> 9 )
print ( x/ 10 ) ;
putchar ( x% 10 + '0' ) ;
}
int main ( ) {
ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. precision ( 10 ) ; cout << fixed;
#ifdef LOCAL_DEFINE
freopen ( "input.txt" , "r" , stdin ) ;
#endif
int kase= 1 ;
scanf ( "%lld" , & tc) ;
while ( tc-- ) {
scanf ( "%lld" , & n) ;
for ( int i= 1 ; i<= n; ++ i) scanf ( "%lld" , & a[ i] ) ;
for ( int i= 1 ; i<= n; ++ i) scanf ( "%lld" , & b[ i] ) ;
ll maxx= LLONG_MIN;
vector< ll> p;
pre[ 0 ] = 0 ;
for ( int i= 1 ; i<= n; ++ i) {
pre[ i] = pre[ i- 1 ] + a[ i] ;
if ( pre[ i] > maxx) {
maxx= pre[ i] ;
p. emplace_back ( i) ;
}
}
for ( int i= 2 ; i<= n; ++ i) {
b[ i] = min ( b[ i] , b[ i- 1 ] ) ;
}
__int128 ans= 0 ;
__int128 use= 0 ;
for ( int i= int ( p. size ( ) ) - 1 ; i>= 0 ; -- i) {
__int128 cnt= b[ p[ i] ] - use;
__int128 num= pre[ p[ i] ] ;
ans+ = cnt* num;
use= b[ p[ i] ] ;
}
printf ( "Case #%d: %lld " , kase++ , b[ 1 ] ) ;
print ( ans) ;
puts ( "" ) ;
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock ( ) / CLOCKS_PER_SEC << " s.\n" ;
#endif
return 0 ;
}
G Game SET 模拟,暴力出奇迹 题意: 有t组数据,每组数据给你n个串,每个串由4个部分组成,每个部分都可以由不同的东西组成,*
表示可以替代任意部分,现在问你存不存在一组三个串答案,使这三个串的每部分要么全都相同,要么全都不相同。 t<=1000 n<=256 解法: 这道题真的是印证了那句话暴力出奇迹,第一眼看t*n^3怎么可能不T,然而有证明只要遍历30个就一定能找到一组解,官方给的题解我就看了一眼,也就10几页吧(,打扰了。 学到了,以后遇到过的队伍多的题,没思路就暴力交一发,万一过了呢。
#include <bits/stdc++.h>
using namespace std;
const int maxn= 500 ;
struct node{
string a[ 5 ] ;
} nd[ maxn] ;
int tc, n;
bool same ( string a, string b) {
if ( a== b) return true ;
if ( a== "*" || b== "*" ) return true ;
return false ;
}
bool diff ( string a, string b) {
if ( a== "*" || b== "*" ) return true ;
if ( a!= b) return true ;
return false ;
}
bool solve ( int t1, int t2, int t3) {
for ( int i= 0 ; i< 4 ; ++ i) {
if ( same ( nd[ t1] . a[ i] , nd[ t2] . a[ i] ) && same ( nd[ t2] . a[ i] , nd[ t3] . a[ i] ) ) continue ;
if ( ! diff ( nd[ t1] . a[ i] , nd[ t2] . a[ i] ) || ! diff ( nd[ t1] . a[ i] , nd[ t3] . a[ i] )
|| ! diff ( nd[ t2] . a[ i] , nd[ t3] . a[ i] ) ) return false ;
}
return true ;
}
int main ( ) {
ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. precision ( 10 ) ; cout << fixed;
#ifdef LOCAL_DEFINE
freopen ( "input.txt" , "r" , stdin ) ;
#endif
int kase= 1 ;
cin>> tc;
while ( tc-- ) {
cin>> n;
bool ok= false ;
string all;
for ( int i= 1 ; i<= n; ++ i) {
cin>> all;
int cnt= 0 ;
string ta, tb, tc, td;
for ( char c: all) {
if ( c== '[' ) ++ cnt;
else if ( c== ']' ) continue ;
else {
if ( cnt== 1 ) ta+ = c;
else if ( cnt== 2 ) tb+ = c;
else if ( cnt== 3 ) tc+ = c;
else td+ = c;
}
}
nd[ i] . a[ 0 ] = ta;
nd[ i] . a[ 1 ] = tb;
nd[ i] . a[ 2 ] = tc;
nd[ i] . a[ 3 ] = td;
}
int ans1, ans2, ans3;
for ( int i= 1 ; i<= n; ++ i) {
for ( int j= i+ 1 ; j<= n; ++ j) {
for ( int k= j+ 1 ; k<= n; ++ k) {
if ( solve ( i, j, k) ) {
ans1= i; ans2= j; ans3= k;
ok= true ;
break ;
}
}
if ( ok) break ;
}
if ( ok) break ;
}
if ( ok) cout<< "Case #" << kase++ << ": " << ans1<< ' ' << ans2<< ' ' << ans3<< '\n' ;
else cout<< "Case #" << kase++ << ": " << - 1 << '\n' ;
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock ( ) / CLOCKS_PER_SEC << " s.\n" ;
#endif
return 0 ;
}