1. 程式人生 > 其它 >AtCoder Beginner Contest 253 A - E

AtCoder Beginner Contest 253 A - E

傳送門

A - Median?

找中間數

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
int num[maxn];

int main()
{
    for(int i=0; i<3; i++) cin >> num[i];
    int a = num[1];
    sort(num, num + 3);
    if(a == num[1]) cout << "Yes" << endl;
    else cout << "No" << endl;

    return 0;
}

B - Distance Between Tokens

找起點和終點的曼哈頓距離

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
string s[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    for(int i=0; i<n; i++)
        cin >> s[i];
    int sx = -1, sy, ex, ey;
    int cnt = 0;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            if(s[i][j] == 'o')
            {
                if(cnt == 0)
                {
                    sx = i;
                    sy = j;
                    cnt++;
                }
                if(cnt == 1)
                {
                    ex = i;
                    ey = j;
                }
            }
        }
    }
    
    
    cout << abs(ex - sx) + abs(ey - sy) << endl;

    return 0;
}

C - Max - Min Query

可以直接用 map 維護就好了

我是用 set 維護,然後 map 判斷什麼時候刪除和增加

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
string s[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int q;
    cin >> q;
    set<int>s;
    map<int, int>vis;
    while(q--)
    {
        int t;
        cin >> t;
        if(t == 1)
        {
            int x;
            cin >> x;
            if(++vis[x] == 1) s.insert(x);
        }
        else if(t == 2)
        {
            int x, cc;
            cin >> x >> cc;
            int way = min(cc, vis[x]);
            vis[x] -= way;
            if(vis[x] == 0 && way != 0) s.erase(x);
        }
        else
        {
            auto it = s.end();
            it--;
            cout << (*it - *s.begin()) << endl;
        }
    }
    return 0;
}

D - FizzBuzz Sum Hard

我寫的極其複雜

直接等差數列,減去 a 的倍數,減去 b 的倍數,加上 a 和 b 的公倍數

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
string s[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll n, a, b;
    cin >> n >> a >> b;
    ll ab = a / __gcd(a, b) * b;
    ll t = n / ab;
    ll sum = 0;
    if(t)
    {
        sum += (1 + ab) * ab / 2;
        sum -= ab * (ab / a - 1) / 2;
        sum -= ab * (ab / b - 1) / 2;
        sum -= ab;
        sum *= t * t;
    }
    // cout << sum << endl;
    if(n % ab)
    {
        ab = t * ab;
        ll ta = (n - ab) / a;
        ll tb = (n - ab) / b;
        sum -= (ab + a + ab + ta * a) * ta / 2;
        sum -= (ab + b + ab + tb * b) * tb / 2;
        sum += (1 + ab + n) * (n - ab) / 2;
    }
    cout << sum << endl;
    return 0;
}

E - Distance Sequence

dp

\(dp[i][j]\) 表示第 \(i\) 個數字是 \(j\) 的時候的方案數

狀態轉移:\(dp[i][j] = \sum{}{} dp[i-1][v]\)\(v\) 表示當第 \(i\) 個數字為 \(j\) 時,第 \(i - 1\) 個數字滿足相差絕對值不小於 \(k\) 的數字

純轉移的話複雜度很高,可以考慮用字首和處理一下,複雜度為 \(O(nm)\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 1010;
const ll inf = 1e17 + 10;
const ll mod = 998244353;
ll dp[maxn][maxn * 5];
ll sum[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll n, m, k;
    cin >> n >> m >> k;
    for(int i=1; i<=m; i++) {dp[0][i] = 1; sum[i] = sum[i-1] + 1;}
    for(int i=1; i<n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ll l = j - k;
            ll r = j + k;
            l++;
            r--;
            l = max(1ll, l);
            r = min(m, r);
            dp[i][j] = (mod + sum[m] - max(0ll, sum[r] - sum[l-1])) % mod;
        }
        for(int j=1; j<=m; j++)
            sum[j] = sum[j-1] + dp[i][j];
        // cout << "now: ";
        // cout << sum[m] << endl;
    }
    cout << sum[m] % mod << endl;
    return 0;
}

F - Operations on a Matrix

F 到現在都沒過,我的想法是對於每次詢問,找到最近的改變行的操作,然後將那個座標的差值用 map 儲存起來

然後列的疊加還是用樹狀陣列維護,但是現在死活過不去