codeforces-1430E(树状数组+逆序对)

codeforces1430E-String Reversal

题目链接:http://codeforces.com/contest/1430/problem/E

题目描述:

给定一个字符串(abcd),将该字符串转换为它的反转字符串(dcba),只可以交换相邻的字符,问一共需要交换多少次

思路:

把字符串倒置,反转字符串的每个字符在原串中一定是优先采取最近的字符移动过来,很显然这种相邻交换字符的方式符合逆序对的计算,比如对于字符串"aabcd"的下标原本是(1,2,3,4,5),反转后的字符串"dcbaa"对应的下标就应该是(5,4,3,1,2),求出的逆序对数9就是交换次数。求逆序对采用了树状数组,维护原串中的字符下标的优先顺序采用了队列。

代码:

#include<bits/stdc++.h>

using namespace std;
using ll = long long;
const ll N = 2e5+5;
const double PI = acos(-1.0);
#define Test ll tesnum;tesnum = read();while(tesnum--)

ll read();
ll C[N],n;
int lowbit(int x){return x&(-x);}
void update(int i,int v)
{
    while(i<=n){
        C[i]+=v;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    ll ans = 0;
    while(i){
        ans+=C[i];
        i-=lowbit(i);
    }
    return ans;
}
int main() {
    cin>>n;
    string s;
    cin>>s;
    queue<int> q[100];
    for(int i = 0; i < n; i++){
        q[s[i]-'a'].push(i+1);
    }
    reverse(s.begin(),s.end());
    ll ans = 0;
    for(int i = 0; i < n; i++){
        int id = q[s[i]-'a'].front();
        update(id,1);
        q[s[i]-'a'].pop();
        ans+=i+1-getsum(id);
    }
    cout<<ans<<endl;
    return "BT7274", NULL;
}

inline ll read() {
    ll hcy = 0, dia = 1;
    char boluo = getchar();
    while (!isdigit(boluo)) {
        if (boluo == '-')dia = -1;
        boluo = getchar();
    }
    while (isdigit(boluo)) {
        hcy = hcy * 10 + boluo - '0';
        boluo = getchar();
    }
    return hcy * dia;
}
posted @ 2020-10-24 01:06  BT-7274  阅读(171)  评论(0编辑  收藏  举报