1. 程式人生 > 其它 >AtCoder Beginner Contest 250 A - E 題解

AtCoder Beginner Contest 250 A - E 題解

傳送門

閒來無事,突然想 vp 一場之前忙的來不及做的

A - Adjacent Squares

這題沒想到居然還會卡了一下

給出一個圖,給出當前位置,看看有多少個格子相鄰

行和列分別判斷就好

#include <iostream>
using namespace std;

int main()
{
    int n, m;
    cin >> n >> m;
    int x, y;
    cin >> x >> y;
    int cnt = 0;
    if(n == 1) cnt += 2;
    else if(x == 1 || x == n) cnt++;
    if(m == 1) cnt += 2;
    else if(y == 1 || y == m) cnt++;
    cout << 4 - cnt << endl;
    return 0;
}

B - Enlarged Checker Board

一個模擬,算了一下並不會爆空間,就直接寫好再列印了

#include <iostream>
using namespace std;
const int maxn = 110;
char s[maxn][maxn];

int main()
{
    int n, a, b;
    cin >> n >> a >> b;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            char now = (i + j) % 2 == 0 ? '.' : '#';
            for(int x=i*a; x<i*a+a; x++)
            {
                for(int y=j*b; y<j*b+b; y++)
                {
                    s[x][y] = now;
                }
            }
        }
    }
    for(int i=0; i<a*n; i++)
    {
        for(int j=0; j<b*n; j++)
            cout << s[i][j];
        cout << endl;
    }
    return 0;
}

C - Adjacent Swaps

這個用桶來處理一下位置,然後每次詢問的時候桶和陣列同時維護

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 10;
int num[maxn], alp[maxn];

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++) num[i] = alp[i] = i;
    while(m--)
    {
        int x;
        scanf("%d", &x);
        if(alp[x] == n) x = num[n-1];
        int way = alp[x];
        int a = num[way];
        int b = num[way + 1];
        swap(num[way], num[way+1]);
        swap(alp[a], alp[b]);
    }
    for(int i=1; i<=n; i++)
    {
        if(i != 1) printf(" ");
        printf("%d", num[i]);
    }
    printf("\n");
    return 0;
}

D - 250-like Number

這個題比較有趣

首先素數的話先用一個尤拉篩預處理一下

接著要尋找合理的情況,本來是想用 \(O(n^2)\) 強行莽一下,但是一直死活寫不對,就突然想到二分,一下就過了

因為 \(k = p * q ^ 3\) 且有 \(p < q\),所以可以列舉 \(q\),然後再找有多少個符合的 \(p\)

而找 \(p\) 的數量,可以直接用二分去尋找第一個大到不符合要求的 \(p\) 的位置,然後知道有多少個 \(p\) 符合條件

這題比較友好的一點是,因為查詢的是素數乘積,所以不會出現說相同一個數字有多種分解的情況,就不用查重,不然還得用一個 set 去維護

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int maxn = 1e6 + 10;
int prime[maxn], tp = 0;
long long p[maxn];

void init()
{
    int n = 1e6 + 1;
    for(int i=2; i<n; i++) prime[i] = 1;
    for(int i=2; i<n; i++)
    {
        if(prime[i])
        {
            p[tp++] = i;
            for(int j=i+i; j<n; j+=i)
                prime[j] = 0;
        }
    }
}

int main()
{
    int t = 0;
    init();
    long long n;
    cin >> n;
    for(int i=0; i<tp; i++)
    {
        long long now = p[i] * p[i] * p[i];
        long long x = n / now;
        t += upper_bound(p, p + i, x) - p;
    }
    cout << t << endl;
    return 0;
}

E - Prefix Equality

這題也很有趣,大概就是問 \(a\) 陣列前 \(x_i\) 個 和 \(b\) 陣列前 \(y_i\) 個,這兩組各自形成的集合是否相等

尺取

我用的是尺取過的,但是看了別人的題解,好像都是用雜湊來預處理 \(a\) 的字首集合 還有 \(b\) 的字首集合,然後直接判斷是否相等

我認為,如果選定了 \(a\) 陣列的前 \(i\) 個,則在 \(b\) 陣列中,一定有一個範圍 \([l, r]\) 使得答案成立

並且對於這個範圍,有 \(l_{i} \leq l_{i+1}\)\(r_{i} \leq r_{i+1}\),因此可以判斷他是單調的,所以直接尺取區間就行,尺取複雜度為 \(O(n)\)

因為要維護一個桶,所以用了 \(map\)

總的時間複雜度為 \(O(nlogn)\)

#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const int maxn = 2e5 + 10;
int a[maxn], b[maxn];
pii num[maxn];

int main()
{
    int n;
    scanf("%d", &n);
    map<int, int> r_vis, l_vis;
    for(int i=1; i<=n; i++) scanf("%d", &a[i]);
    for(int i=1; i<=n; i++) scanf("%d", &b[i]);
    b[++n] = a[1];
    int l = 1, r = 1, cnt = 0;
    for(int i=1; i<=n; i++)
    {
        if(r_vis[a[i]] == 0) r_vis[a[i]] = 1;
        if(l_vis[a[i]] == 0) {cnt++; l_vis[a[i]] = 1;}
        while(l <= n && cnt > 0)
        {
            if(l_vis[b[l]] == 1) cnt--;
            l_vis[b[l]] = 2;
            l++;
        }
        while(r <= n && r_vis[b[r]]) r++;
        num[i] = make_pair(l - 1, r - 1);
    }
    int m;
    scanf("%d", &m);
    for(int i=0; i<m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        if(y >= num[x].first && y <= num[x].second) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}