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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章