目录

牛客练习赛135小柒的逆序对2

牛客练习赛135——小柒的逆序对(2)

这里还得说一下,调换一个排列中任意两个不同的数,该排列的逆序数奇偶会改变

题目:

https://i-blog.csdnimg.cn/direct/76356740f7f24ae78ffeade6fcc0ab51.png

思路:

这道题的数据给的很大,如果我们用树状数组维护前缀和都没用,但是我们观察到英文字符只有26个,那我们可以开一个二维数组g[i][j]表示ij字符对有多少个

如何维护这个数组呢,其实也很简单,遍历s每个字符c,同时开一个数组储存26个字符

对于字符c,先遍历26个字符y,将g[y][c]加上y的个数,结束后再将c的数量加一

(对于这个维护,其实反过来遍历应该也是可以的)

那么提前维护好了字符对,接下来每次查找就容易多了

我们每次查找都直接暴力两层遍历,如果k的字典序大于j,那么答案就要加上g[k][j](逆序对的定义)

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#define ll long long
using namespace std;

int n, q;
string s;
string f;
int g[30][30];
int cnt[30];
int pos[30];
void solve()
{
    cin >> n >> q;
    cin >> s;
    for (char c : s) 
    {
        int idx = c - 'a';
        for (int y = 0; y < 26; y++)
        {
            g[y][idx] += cnt[y];
        }
        cnt[idx]++;
    }
    for (int i = 0; i < q; i++)
    {
        cin >> f;
        for (int y = 0; y < 26; y++)
            pos[f[y] - 'a'] = y;
        ll res = 0;
        for (int j = 0; j < 26; j++)
        {
            for (int k = 0; k < 26; k++)
            {
                if (pos[k] > pos[j])
                    res += g[k][j];
            }
        }
        cout << res << endl;
    }
}

int main()
{
    cin.tie(0)->sync_with_stdio(false);
    int t = 1;
    //cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}