1. 程式人生 > 其它 >Atcoder Beginner Contest 243 部分題解

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;
}