Atcoder Beginner Contest 243

Atcoder Beginner Contest 243 部分题解

A - Shampoo

有一个容积为V的水箱,每天有FMT三个人用水,分别用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抵消前面的LR,抵消后在操作就好了

#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;
}
posted @ 2022-03-14 19:52  PHarr  阅读(69)  评论(0编辑  收藏  举报