cf1430e

这道题当时CF打了,赛后得知有一种非常精妙的写法,因为他是要把字母倒过来问我们要走几步,那么就给每个字母倒过来赋个值,然后在交换顺序后把值放进去做一个逆序对就可以了

下附代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 #define ll long long
 5 using namespace std;
 6 vector<int> cnt[30];
 7 int a[200005],b[200005];
 8 char s[200005];
 9 ll res=0;
10 void merge(int l,int r){
11     if (l==r) return ;
12     int mid=(l+r)>>1;
13     merge(l,mid);
14     merge(mid+1,r);
15     int k=0,i=l,j=mid+1;
16     while (i<=mid && j<=r){
17         if (a[i]<=a[j]) b[++k]=a[i++];
18         else b[++k]=a[j++],res+=mid-i+1;
19     }
20     while (i<=mid) b[++k]=a[i++];
21     while (j<=r) b[++k]=a[j++];
22     for (int i=l,j=1; i<=r; ++i,++j) a[i]=b[j];
23 }
24 int main(){
25     int n;
26     scanf("%d",&n);
27     scanf("%s",s+1);
28     for (int i=n; i>=1; i--){
29         cnt[s[i]-'a'].push_back(i);
30     }
31     for (int i=1; i<=n/2; i++)
32         swap(s[i],s[n-i+1]);
33     for (int i=1; i<=n; i++){
34         a[i]=cnt[s[i]-'a'].back(),cnt[s[i]-'a'].pop_back();
35     }
36     res=0;
37     merge(1,n);
38     printf("%lld",res);
39 }
View Code
原文地址:https://www.cnblogs.com/i-caigou-TT/p/13887413.html