反转字符串

/*
abddea
aeddba
先预处理队列,a['c'],表示c所有出现的位置,用一个pop一次。
找到了右边最近的出现位置k,则看k前面还剩几个元素,剩几个元素答案加几,
在把k位置删除。
*/
#include <bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define endl "\n"
typedef long long LL;
const int N = 2e5 + 10, M = N, mod = 1e9 + 7;
using namespace std;
int t[N], n;
char a[N], b[N];
int lowbit(int x) {return x & -x;}
void add(int x, int c){
    for(int i = x; i <= n; i += lowbit(i)){
        t[i] += c;
    }
}
LL query(int x){
    LL sum = 0;
    for(int i = x; i; i -= lowbit(i)){
        sum += t[i];
    }
    return sum;
}
queue<int> q[26];
int main()
{
    CLOSE;
    cin >> n >> (a + 1);
    for(int i = 1, j = n; i <= n; i ++, j --){
    	q[a[i] - 'a'].push(i);
    	b[j] = a[i];//存反转的字符串
    	add(i, 1);//该位置表示未被删除
	}
    int cnt = 0;
    for(int i = 1; i <= n; i ++){
		int k = q[b[i] - 'a'].front();//右边最近的位置
		q[b[i] - 'a'].pop();
		cnt += query(k - 1);//前面还剩几个元素,则移动几次
		add(k, -1);//删除这个元素
    }
    cout << cnt;
    return 0;
}
posted @ 2024-02-02 14:21  可爱的卤蛋  阅读(11)  评论(0编辑  收藏  举报