[Codeforces 1430E] String Reversal | Reverse order pair, tree array, thinking

Subject link: https://codeforces.com/contest/665/problem/D

Main idea:

Given a string s, sinvert the string to form a string. t
You can operate on the string seach time, and you can exchange two adjacent characters each time.
Ask how many times the minimum exchange can makes->t

Question idea:

The remaining problems when preparing for CCPC to brush the question.
First, sinvert the string to form a string. The t
swap operation first considers the reverse pair:
将一段序列进行冒泡排序,进行相邻交换,最后的交换次数最少为:逆序对总和
Then you can consider this question:
Let each position of the final state t become the last ordered sequence
abcde -> 12345
aabbb -> 12345
. The first example Let’s see, after the flip, it becomes 54321, so the reverse pair is the answer. In the
second example, after the flip, it becomes 54321, but the reverse pair is not the answer at this time
. Why?
Because, at this time, aa does not need to be exchanged, that is to say, aa is the same element, and there is no need to consider who is ahead and who is behind.
So, sort the same element internally, that is, the second example becomes: 45123 after inversion
.

In addition, there is a tree-like array that is directly maintained. There are several numbers in front of the current position, and the idea is relatively easy to understand. It is roughly divided into two steps:
1. Record the appearance position of each letter
2. Move the nearest letter to each time The current position, the process is maintained by a tree array

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 4e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll num[maxn];
vector<int>v[30];
char s[maxn];
int c[maxn];
ll sum[maxn];
void add(int pos){
    
    
    while(pos<=n){
    
    
        sum[pos]++;
        pos += pos&-pos;
    }
}
ll GetSum(int pos){
    
    
    ll ans = 0;
    while(pos){
    
    
        ans += sum[pos];
        pos -= pos&-pos;
    }return ans;
}
int main(){
    
    
    ///11123
    ///32111
    read(n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
        v[s[i]-'a'].push_back(i);
    for(int i=0;i<26;i++){
    
    
        int sz =v[i].size();
        for(int l = 0,r = sz-1;l<sz;l++,r--){
    
    
            int x = v[i][l];
            c[n-x+1] = v[i][r];
        }
    }
    ll ans = 0;
    for(int i=1;i<=n;i++){
    
    
        ans += GetSum(n)-GetSum(c[i]);
        add(c[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

/***
aaaza
azaaa
****/

Guess you like

Origin blog.csdn.net/qq_43857314/article/details/111633708