abc371

你说得太对辣發表於2024-09-15

傳送門

A.

模擬。

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 7;
int main() {
    string a, b, c;
    cin >> a >> b >> c;
    if(a == "<") {
        if(c == "<") cout << "B" << endl;
        else {
            if(b == "<") cout << "C" << endl;
            else cout << "A" << endl;
        }
    }
    else {
        if(b == "<") cout << "A" << endl;
        else {
            if(c == "<") cout << "C" << endl;
            else cout << "B" << endl; 
        }
    }
    return 0;
}

B.

模擬。

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 7;
int vis[N];
int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= m; i ++) {
        int a;
        string b;
        cin >> a >> b;
        if(b == "F") {
            cout << "No" << endl;
        }
        else {
            if(!vis[a]) {
                cout << "Yes" << endl;
                vis[a] = 1;
            }
            else cout << "No" << endl;
        }
    }
    return 0;
}

C.

題意為,給兩個無向圖 \(M_G, M_H\),每次可以選 \(M_H\) 的兩點 \(i, j\),刪去這條邊或加上這條邊,花費 \(a_{i,j}\),問最少花費多少使得兩個圖同構。

注意到 \(n \le 8\),可以對 \(M_G\) 全排列,然後 \(n^2\) 更新最小值,時間複雜度 \(O(n!n^2)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 200;
vector<int> g1[N], g2[N];
int a[N][N];
int p1[N][N], p2[N][N];
int pp[N];
signed main() {
    int n, m1, m2;
    cin >> n >> m1;
    for(int i = 1; i <= m1; i ++) {
        int x, y;
        cin >> x >> y;
        p1[x][y] = 1;
        p1[y][x] = 1;
    }
    cin >> m2;
    for(int i = 1; i <= m2; i ++) {
        int x, y;
        cin >> x >> y;
        p2[x][y] = 1;
        p2[y][x] = 1;
    }
    for(int i = 1; i <= n; i ++) {
        for(int j = i + 1; j <= n; j ++) {
            cin >> a[i][j];
        }
    }
    int cnt = 0x3f3f3f3f;
    for(int i = 1; i <= n; i ++) pp[i] = i;
    do{
        int ans = 0;
        for(int i = 1; i <= n; i ++) {
            for(int j = i + 1; j <= n; j ++) {
                if((p1[pp[i]][pp[j]] && p2[i][j]) || (!p1[pp[i]][pp[j]] && !p2[i][j])) continue;
                ans += a[i][j];
            }
        } 
        cnt = min(cnt, ans);
    }while(next_permutation(pp + 1, pp + n + 1));
    
    cout << cnt << endl;
    return 0;
}

D.

\(n\) 個村莊,座標 \(x_i\),有 \(p_i\) 人,\(q\) 組詢問,座標 \(l_i, r_i\) 之間有多少人。

\(-10^9 \le x_i \le 10^9\),對 \(n\) 個村莊字首和,二分 \(l_i, r_i\) 的右邊第一個村莊。

#include<bits/stdc++.h>
#define int long long
using namespace std;

struct Village {
    int x;
    int p;
};
bool compare(const Village &a, const Village &b) {
    return a.x < b.x;
}

signed main() {
    int n;
    cin >> n;

    vector<Village> villages(n);
    for (int i = 0; i < n; ++i) {
        cin >> villages[i].x;
    }
    for (int i = 0; i < n; ++i) {
        cin >> villages[i].p;
    }
    sort(villages.begin(), villages.end(), compare);
    vector<long long> prefix(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        prefix[i] = prefix[i - 1] + villages[i - 1].p;
    }
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int L, R;
        cin >> L >> R;
        int ll = lower_bound(villages.begin(), villages.end(), Village{L, 0}, compare) - villages.begin();
        int rr = upper_bound(villages.begin(), villages.end(), Village{R, 0}, compare) - villages.begin() - 1;
        if (left <= right) {
            cout << prefix[rr + 1] - prefix[ll] << endl;
        } else {
            cout << 0 << endl;
        }
    }

    return 0;
}

E.

\(\sum_{i=1}^{n}\sum_{j=i}^{n} f(i,j)\)\(f(i,j)\) 表示子串 \((s_i, ..., s_j)\) 的字元種類數。

發現加入一個 \(x\),較 \(lst[x]\) 多出了 \((i - lst[x])\) 個區間(可以理解為,區間的左端點個數不變,右端點可選擇的多了 \(i - lst[x]\)),然後按照這個模擬即可。


#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e6 + 7;
int lst[N], ans, a[N], now;
signed main() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) {
        now += (i - lst[a[i]]);
        ans += now;
        lst[a[i]] = i;
    }
    cout << ans << endl;
}