AT_abc360_d [ABC360D] Ghost Ants

· · 题解

题解中大部分都是二分和双指针,这里给出一个逆序对的题解,其实由于每个蚂蚁都有自己的方向且不会变,那么很明显的我们走完路程之后,如果原来标号小的蚂蚁走到了标号大的蚂蚁的后面那么两者一定相遇,所以可以使用逆序对。

但是有以下几点需要注意:

顺便给出一组样例

5
26
00011
-28 -55 48 -4 89

下面奉上代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
struct node{
    int x, id, s;
    bool operator<(const node &w) const{
        if(x == w.x) return id > w.id;
        else return x < w.x;
    }
}a[N];
int c[N], res;
bool cmp(node a, node b){
    return a.x < b.x;
}
void merge_sort(int l, int r){
    if(l == r) return;
    int mid = l + r >> 1, i = l, j = mid + 1, num = l;
    merge_sort(l, mid), merge_sort(mid + 1, r);
    while(i <= mid && j <= r){
        if(a[i].id <= a[j].id) c[num++] = a[i++].id;
        else res += mid - i + 1, c[num++] = a[j++].id;
    }
    while(i <= mid) c[num++] = a[i++].id;
    while(j <= r) c[num++] = a[j++].id;
    for(int i = l; i <= r; i++) a[i].id = c[i];
}
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, t; cin >> n >> t;
    string s; cin >> s;
    s = " " + s;
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        a[i] = {x, i, s[i] - '0'};  
    }
    sort(a + 1, a + 1 + n, cmp);
    for(int i = 1; i <= n; i++){
        a[i].id = i;
        if(a[i].s == 1) a[i].x += t;
        else a[i].x -= t;
    }
    sort(a + 1, a + 1 + n);
    merge_sort(1, n);
    cout << res << '\n';
    return 0;
}