ICPC杭州站K

227 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
K - Master of Both

Professor Hui-Bot is the master of string theory and advanced data structures, so he came up with an interesting problem. Given a sequence of nn strings consisting of only lowercase English letters, how many inversions are there in this sequence when the strings are compared by lexicographical order?
As the most extraordinary student of Hui-Bot, Putata and Budada mastered superb string theory and advanced data structure skills respectively, and they solved this problem together with ease. However, there are qq different parallel universes, where the characters in the alphabet are not appearing in the original order.
Formally, the alphabet in each universe is a string, which is a permutation of the 2626 lowercase English letter, denoting the order each character appears.
A string aa is lexicographically smaller than a string bb if and only if one of the following holds:
aa is a prefix of bb, but aba\neq b; in the first position where aa and bb differ, the string aa has a letter that appears earlier in the alphabet than the corresponding letter in bb. The number of inversions in a sequence aa of length nn is the number of ordered pairs (i,j)(i,j) such that 1i<jn1\leq i<j\leq n, aj<aia_j<a_i.
Please help Putata and Budada in each universe to solve the problem.

中文大意

给我们n个字符串然后输入q个英文字母的全排列定义现在的字典序根据这个排序求出现在的逆序对

解法

对于一个字符串我们只需要找出第一个不同的两个位置,然后比较一下即可

Code

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

const int N = 1e6 + 10;

ll a[27][27] ,b[27], c[N][27], tot, cnt[N], res;
char s[N];

void insert(char *s) {
    int n = strlen(s + 1);
    int p = 0;
    for(int i = 1; i <= n; i++) {
        int x = s[i] - 'a';
        for(int j = 0; j < 26; j++) {
            if(j != x && c[p][j]) a[j][x] += cnt[c[p][j]];
        }
        if(!c[p][x]) c[p][x] = ++tot;
        p = c[p][x];
        cnt[p] ++; 
    }
    for(int j = 0; j < 26; j++) {
        if(c[p][j]) {
            res += cnt[c[p][j]];
        }
    }
}

void solve() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
         scanf("%s", s + 1);
         insert(s);
    }
    while(m -- ) {
        scanf("%s",s + 1);
        int k = strlen(s + 1);
        for(int i = 1; i <= k; i++) b[s[i] - 'a'] = i;
        ll ans = 0;
        for(int i = 0; i < 26; i++)
            for(int j = 0; j < 26; j++) {
                if(b[j] < b[i]) ans += a[i][j];
            }
        printf("%lld\n", ans + res);
    }
}

int main()
{
    int T = 1;
    // scanf("%d", &T);
    while(T--) solve();
    return 0;
}