AtCoder Beginner Contest 229
A - First Grid
\(2\times 2\)矩阵只有两种情况不满足
.# #.
#. .#
特判即可
如果一个#
相邻的三个格子全是.
则一定不可能联通
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2;
cin >> s1 >> s2;
if(s1=="#." && s2==".#"){cout << "No\n";}
else if(s1==".#" && s2=="#."){cout << "No\n";}
else{cout << "Yes\n";}
return 0;
}
B - Hard Calculation
判断a+b的过程中是否进位
判断是否有一位相加大于9即可
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long a , b , x , y ;
cin >> a >> b;
while( a && b )
{
x = a % 10 , y = b % 10 , a /= 10 , b /= 10;
if( x + y >= 10 )
{
cout << "Hard\n";
return 0;
}
}
cout << "Easy\n";
return 0;
}
C - Cheese
给\(N\)中奶酪,每种奶酪的美味值是\(A_i\)每克,每种奶酪有\(B_i\)克,最多选择\(W\)克,问美味值最大是多少
贪心选择美味值高的
#include<bits/stdc++.h>
using namespace std;
#define a first
#define b second
long long n , w , res ;
vector< pair< long long , long long > > p;
int main()
{
cin >> n >> w ;
for( int i = 1 , x , y ; i <= n ; i ++ ) cin >> x >> y , p.push_back( { x , y } );
sort( p.begin() , p.end() , greater< pair< int ,int > >() );
for( int i = 0 ; i < n && w ; i ++ )
{
if( p[i].b <= w ) res += p[i].a * p[i].b , w -= p[i].b;
else res += p[i].a * w , w = 0;
}
cout << res << endl;
}
D - Longest X
给一个字符串\(S\)只由X
或.
组成,共有\(K\)次操作,每次可以任意把一个.
换成x
,不一定要用完\(K\)次操作,问操作做后最长的连续\(X\)有多长
前缀和统计[1,i]
有多少个.
,这样可以\(O(1)\)求解任意区间内.
的数量
二分答案,暴力的枚举区间的端点,判断区间内.
的个数是否小于\(K\)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n , a[N] , k , res;
string s;
bool check( int len )
{
for( int i = len ; i <= n ; i ++ )
{
if( a[i] - a[ i - len ] <= k ) return 1;
}
return 0;
}
int main()
{
cin >> s >> k;
n = s.size();
for( int i = 1 ; i <= n ; i ++ ) a[i] = a[i-1] + ( s[ i - 1 ] == 'X' ? 0 : 1 );
int l = 1 , r = n , mid;
while( l <= r )
{
mid = ( l + r ) >> 1;
if( check(mid) ) res = mid , l = mid + 1;
else r = mid - 1;
}
cout << res << endl;
return 0;
}
E - Graph Destruction
给一个图\(N\)个点、\(M\)条边。每条边连接\(A_i\)和\(B_i\)。会一个接一个的删除\(1,2,\cdots,N\)点。删除点\(i\)意味着从图中删除点和他所连的所有边。问每次删除点后,图中有多少给联通块。
倒叙枚举,每次加点,加点的过程中加边,用并查集来维护连通块。
加边的时候两个端点不一定同时存在在图中,所以存边的时候保证\(A_i<B_i\)这样在加\(A_i\)所连的边时\(B_i\)一定在图中。
并查集维护时,如果边的两个端点属于不同的连通块,加边后连通块数量就会减一。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n , m , res[N] , fa[N];
vector< int > e[N];
int getfa( int x )
{
if( fa[x] == x ) return x;
return fa[x] = getfa( fa[x] );
}
bool merge( int x , int y )
{
int fx = getfa( x ) , fy = getfa(y);
if( fx == fy ) return 0;
fa[fx] = fy;
return 1;
}
int main()
{
cin >> n >> m;
for( int i = 1 ; i <= n ; i ++ ) fa[i] = i;
for( int i = 1 , x , y ; i <= m ; i ++ )
{
cin >> x >> y;
if( x > y ) e[y].push_back(x);
else e[x].push_back(y);
}
for( int i = n - 1 ; i >= 1 ; i -- )
{
res[i] = res[ i + 1 ] + 1;
for( auto v : e[ i + 1 ] ) if( merge( v , i + 1 ) ) res[i]--;
}
for( int i = 1 ; i <= n ; i ++ ) cout << res[i] << endl;
return 0;
}