Codeforces Round 918 (Div. 4) 题解 | JorbanS

A - Odd One Out

int solve() {
    int a, b, c; cin >> a >> b >> c;
    if (a == b) return c;
    if (a == c) return b;
    return a;
}

B - Not Quite Latin Square

char solve() {
    int sum = ('A' + 'B' + 'C') * 3 + '?';
    for (int i = 0; i < 3; i ++) {
        cin >> s[i];
        for (int j = 0; j < 3; j ++) sum -= s[i][j];
    }
    return (char)sum;
}

C - Can I Square?

string solve() {
    cin >> n;
    ll res = 0;
    for (int i = 0; i < n; i ++) {
        int x; cin >> x;
        res += x;
    }
    ll x = sqrt(res);
    return x * x == res ? yes : no;
}

D - Unnatural Language Processing

void solve() {
    cin >> n >> s;
    for (int i = 0; i < n; i ++) {
        cout << s[i];
        if (i + 2 < n && (s[i + 2] == 'a' || s[i + 2] == 'e')) cout << '.';
    }
    cout << endl;
}

E - Romantic Glasses

int n, m;
int a[N];
ll pre[N];

string solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        pre[i] = pre[i - 1] + a[i] * pow(-1, i & 1);
    }
    map<ll, bool> mp;
    mp[0] = true;
    for (int i = 1; i <= n; i ++) {
        if (mp[pre[i]]) return yes;
        else mp[pre[i]] = true;
    }
    return no;
}

F - Greetings

可以发现只有下列情况计算一次贡献,即区间包含关系

L[        ]R
  l[  ]r

法一:树状数组,每次在 L < l LL<l 的集合中查询,有多少个 R > r R>r R>r

int n, m;
int l;
pii a[N];
int b[N];
int tr[N];

inline int lowbit(int x) { return x & -x; }

void update(int x, int k = 1) {
    while (x <= l) {
        tr[x] += k;
        x += lowbit(x);
    }
}

int query(int x) {
    int res = 0;
    while (x) {
        res += tr[x];
        x -= lowbit(x);
    }
    return res;
}

ll solve() {
    cin >> n;
    for (int i = 0; i < n; i ++) {
        cin >> a[i].aa >> a[i].bb;
        b[i] = a[i].bb;
    }
    sort(a, a + n);
    sort(b, b + n);
    l = unique(b, b + n) - b;
    for (int i = 0; i <= l; i ++) tr[i] = 0;
    ll res = 0;
    for (int i = 0; i < n; i ++) {
        int x = lower_bound(b, b + n, a[i].bb) - b;
        res += query(l - x);
        update(l - x);
    }
    return res;
}

法二:用 vectorerase 函数,奇怪的是复杂度为 O ( n 2 ) O(n^2) O(n2),竟然过了

int n, m;
pii a[N];
int b[N];

ll solve() {
    cin >> n;
    vector<int> b;
    for (int i = 0; i < n; i ++) {
        cin >> a[i].aa >> a[i].bb;
        b.push_back(a[i].bb);
    }
    sort(a, a + n);
    sort(b.begin(), b.end());
    ll res = 0;
    for (int i = 0; i < n; i ++) {
        auto it = lower_bound(b.begin(), b.end(), a[i].bb);
        res += it - b.begin();
        b.erase(it);
    }
    return res;
}

法三:排序使得 a i < a j a_i\lt a_j ai<aj,只要统计 b i > a j b_i\gt a_j bi>aj 的数量,归并排序统计逆序对

ai[        ]aj
  bi[  ]bj
int n, m;
pii a[N];
int q[N], t[N];
ll res = 0;

void mergeSort(int l, int r) {
    if (l == r) return;
    int mid = l + r >> 1;
    mergeSort(l, mid), mergeSort(mid + 1, r);
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r) {
        if (q[i] <= q[j]) t[k ++] = q[i ++];
        else {
            res += mid - i + 1;
            t[k ++] = q[j ++];
        }
    }
    while (i <= mid) t[k ++] = q[i ++];
    while (j <= r) t[k ++] = q[j ++];
    for (int i = l, k = 0; i <= r; i ++, k ++) q[i] = t[k];
}

ll solve() {
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> a[i].aa >> a[i].bb;
    sort(a, a + n);
    for (int i = 0; i < n; i ++) q[i] = a[i].bb;
    res = 0;
    mergeSort(0, n - 1);
    return res;
}

你可能感兴趣的:(OI,题解,算法,c++)