Atcoder Beginner Contest 243
Atcoder Beginner Contest 243 部分题解
A - Shampoo
有一个容积为V
的水箱,每天有F
、M
、T
三个人用水,分别用a、b、c的水,在不加水的情况下谁先不够用
先取模,然后逐个判断就好
#include<bits/stdc++.h>
using namespace std;
int main()
{
int v , a , b , c ;
cin >> v >> a >> b >> c ;
if( v >= a + b + c )
v %= (a+b+c);
if( v >= a )
v-= a;
else
{
cout << "F";
return 0;
}
if( v >= b )
v -= b;
else{
cout << "M";
return 0;
}
cout << "T";
return 0;
}
B - Hit and Blow
给定长度为n的两个数列,问有多少个\(a_i=b_i\),问有多少个既在a中又在b中,且位置不同
把a放在集合中,读入b的时候判读就好了
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
int n , a[N] , b[N] , cnt1 , cnt2;
set<int> c;
inline int read()
{
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int main()
{
n = read();
for( int i = 1 ; i <= n ; i ++ )
a[i] = read() , c.insert(a[i]);
for( int i = 1 , x ; i <= n ; i ++ )
{
x = read();
if( a[i] == x )
cnt1 ++;
else if( c.count(x) )
cnt2 ++;
}
cout << cnt1 << '\n' << cnt2 << endl;
return 0;
}
C - Collision 2
在一个网格图给出每个人的位置的行进方向(只有左右),只要有人对向而行就会相撞,问是否有人相撞
首先要把行数哈希一下,动态的维护每一行向左的最有和向右的最左,每次判断一下就好
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n , xd[N] , yd[N] , l[N] , r[N] ;
string s;
inline int read()
{
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int main()
{
n = read();
for( int i = 1 ; i <=n ; i ++ )
yd[i] = read() , xd[i] = l[i] = read() ;
sort( l + 1 , l+1+n );
for( int i = 1 ; i <= n ; i ++ )
xd[i] = lower_bound( l+1 , l+1+n , xd[i] ) -l;
for( int i = 1 ; i <= n ; i ++ )
l[i] = -1 , r[i] = 0x7f7f7f7f;
cin >> s;
for( int i = 1 ; i <= n ; i ++ )
{
if( s[i-1] == 'L' )
{
if( r[ xd[i] ] < yd[i] )
printf("Yes\n") , exit(0);
l[ xd[i] ] = max( l[xd[i]] , yd[i] );
}
else{
if( l[xd[i]] > yd[i] )
printf("Yes\n") , exit(0);
r[ xd[i] ] = min( r[xd[i]] , yd[i] );
}
}
printf("No\n");
return 0;
}
D - Moves on Binary Tree
在一个满二叉树上,给定初始位置,有x次操作,U
移动到父亲节点L
移动到左儿子R
移动到右儿子
问x次操作后在哪里,如果直接做的话回到导致溢出,如果先移动到儿子在移动到父亲是无效的,所以可以在原操作序列中用U
抵消前面的L
或R
,抵消后在操作就好了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5+5;
ll n , m ;
string s;
vector<char> t;
int main()
{
cin >> m >> n >> s;
for( auto it : s )
{
if( it == 'U' )
{
if( t.size() && *t.rbegin() != 'U' )
t.pop_back();
else t.push_back('U');
}
else t.push_back( it );
}
for( auto it : t )
{
if( it == 'U' )
n >>= 1;
else if( it == 'L' )
n <<= 1;
else n <<= 1 , n |= 1;
}
cout << n << endl;
return 0;
}
E - Edge Deletion
给一个无向图,问最多删除条边后所有点之间的最短路不变
首先要做多源最短路,自然而然就是Floyed,在做FLoyed的过程中如果存在一条边可以被替换掉就说明这条边可以被删除
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 305 , M = 45005 , inf = 0x7f7f7f7f;
ll n , m , dis[N][N] , u[N] , v[N] , w[N] , cnt , vis[N][N];
inline int read()
{
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int main()
{
n = read() , m = read();
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= n ; j ++ )
dis[i][j] = inf;
for( int i = 1 , u , v , w ; i <= m ; i ++ )
u = read() , v = read() , w = read() , dis[u][v] = dis[v][u] = w , vis[u][v] = vis[v][u] = 1;
for( int k = 1 ; k <= n ; k ++ )
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= n ; j ++ )
if( dis[i][j] >= dis[i][k] + dis[k][j] ){
dis[i][j] = dis[j][i] = dis[i][k] + dis[k][j];
if( vis[i][j] ) cnt++ , vis[j][i] = vis[i][j] = 0;
}
cout << cnt << endl;
return 0;
}